2016-08-16 9 views
8

В следующем коде, «ситуация 1» работает как и ожидалось, на всех составителей тестируемых, однако «ситуация 2» это кажется ведут себя по-разному на основе компилятора используемый.Необъяснимые расхождения при копировании и модифицирующие СТД :: строки

В качестве примера MSVC имеет sit1 и sit2 дают одинаковые результаты, однако при использовании GCC/лязг и libstdC++, изменение происходит в исходной строки, и это копия (вроде строки КПС) даже если Я строю с использованием коммутатора C++ 11.

#include <iostream> 
#include <string> 

int main() { 

    // situation 1 
    { 
     std::string x0 = "12345678"; 
     std::string x1 = x0; 

     char* ptr = &x0[0] + 3; 

     (*ptr) = ' '; 

     std::cout << "1. x0: " << x0 << "\n"; 
     std::cout << "1. x1: " << x1 << "\n"; 

     if ((&x0[0]) == x0.data()) std::cout << "1. ptrs are equal\n"; 

    } 

    // situation 2 
    { 
     std::string x0 = "12345678"; 
     std::string x1 = x0; 

     char* ptr = const_cast<char*>(x0.data() + 3); 

     (*ptr) = ' '; 

     std::cout << "2. x0: " << x0 << "\n"; 
     std::cout << "2. x1: " << x1 << "\n"; 

     if ((&x0[0]) == x0.data()) std::cout << "2. ptrs are equal\n"; 
    } 

    return 0; 
} 

GCC (6,1)

1. x0: 123 5678 
1. x1: 12345678 
1. ptrs are equal 
2. x0: 123 5678 
2. x1: 123 5678 
2. ptrs are equal 

MSVC (2015)

1. x0: 123 5678 
1. x1: 12345678 
1. ptrs are equal 
2. x0: 123 5678 
2. x1: 12345678 
2. ptrs are equal 

Есть ли причина расхождений в поведении между различными компиляторами - при условии, что & х0 [0] и .data() возвращают тот же адрес?

+0

[Этот GCC 6.1] (http://melpon.org/wandbox/permlink/cJZq0ey2qv526sJU) ведет себя правильно. –

+5

Вы действительно должны были заменить '4' на' Z'? Не могли бы вы найти что-то, что еще труднее отличить визуально, например 'l' и' I'? Половина удовольствия задавать вопросы на SO делает все возможное, чтобы кто-нибудь мог определить важные детали. –

+2

Я действительно надеюсь, что вы спросите об этом, потому что вы портируете древний, ужасный код, который вы сами не пишете. –

ответ

15

Положение 2 причины неопределенное поведение:

char* ptr = const_cast<char*>(x0.data() + 3); 

(*ptr) = 'Z'; 

В соответствии со спецификацией std::basic_string::data (C++ 14 [string.accessors]/3):

Требуется: Программа должна не изменяйте значения, сохраненные в массиве символов.

Другими словами, вы не можете откинуть на const и изменить строку с помощью указателей, возвращаемых data() или c_str().

+0

, но указательные адреса одинаковы? и не означает ли стандарт, что x0.data() и & x0 [0] должны быть одинаковыми? –

+0

@JacobiJohn они должны быть одного и того же адреса, однако вам разрешено изменять только с помощью версии '& x [0]'. Для реализации копирования на запись, 'operator []' будет делать копию в случае, если результат будет изменен, но '.data()' не будет. –

+0

@ M.M Модифицируемый, не модифицированный. Коду не известно, будет ли он действительно изменен. Другими словами, 'x [0]' на экземпляре/ссылке не const const уже вызывает копию, даже если ничего не сделано с результатом. –