2016-08-16 17 views
8

, "상황 1"그러나 테스트 한 모든 컴파일러에 예상대로 작품, "상황이" 익숙한.설명 할 수없는 차이가 컴파일러에 따라 다르게 행동 것으로 보인다 복사 및 수정 표준 : : 문자열 다음 코드에서

예로 MSVC는 sit1을 갖고 있지만 , 변형이 원래 문자열 발생 ++ GCC/연타 및 된 libstdc를 사용하는 경우, 동일한 결과를 sit2 그리고 비록 (일종의 COW 문자열 등)를 복사 있어 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는 (2,015)

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

다양한 컴파일러 사이의 동작의 차이에 대한 이유가 - 주어진 & X0 [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)에 따르면

이 필요합니다 프로그램하여야한다 문자 배열에 저장된 값을 변경하지 않습니다. 즉

는, 당신은 data() 또는 c_str()에 의해 반환 된 포인터를 통해 const을 멀리 캐스팅 문자열을 수정할 수 없습니다.

+0

하지만 포인터 주소가 동일합니까? x0.data()와 & x0 [0]이 같아야한다는 표준은 아닙니까? –

+0

@JacobiJohn 그들은 동일한 주소 여야하지만'& x [0]'버전을 통해서만 수정할 수 있습니다. copy-on-write 구현의 경우,'operator []'는 결과가 변경 될 경우를 대비해 복사본을 만들지 만'.data()'는 복사하지 않습니다. –

+0

@ M.M 수정할 수 있으며 수정되지 않았습니다. 코드가 실제로 수정 될지 여부를 알 수있는 방법이 없습니다. 다른 말로 표현하자면, 비 const 문자열 인스턴스/참조에있는'x [0]'은 결과를 더 이상 수행하지 않아도 이미 사본을 생성합니다. –