2013-04-07 2 views
2

"샘플"에 대한 s 및 s2 내부 포인터가 동일하지 않다는 것에 놀랐습니다. 설명은 무엇입니까?std :: move - std :: string - 내부 포인터

#include <string> 
#include <cassert> 

int main() 
{ 
    std::string s("sample"); 

    std::string s2(std::move(s)); 

    assert(
     reinterpret_cast<int*>(const_cast<char*>(s.data())) == 
     reinterpret_cast<int*>(const_cast<char*>(s2.data())) 
     ); // assertion failure here  

    return 1; 
} 
+1

제쳐두고, 왜 캐스트가 되었습니까? 그들은 아무 것도하지 않습니다. 's.data() == s2.data()'는 동일합니다. –

+0

나는 adresses를 인쇄하여 두 번째로 assert로 전환했기 때문에 ... 쓰기를 간소화하는 것을 잊어 버렸습니다. – Guillaume07

답변

3

왜 동일해야한다고 생각하십니까? 이동 생성자를 사용하여 s2s에서 구성하고 있습니다. 이렇게하면 s의 데이터 소유권이 s2으로 전송되고 s은 "비어있는"상태로 남습니다. 표준에서는이 작업이 무엇을 의미하는지 자세히 설명하지 않지만 그 후에 s의 데이터에 액세스하면 (다시 할당하지 않고) 정의되지 않습니다.

class string { 
    char* buffer; 

public: 

    string(char const* from) 
     : buffer(new char[std::strlen(from) + 1]) 
    { 
     std::strcpy(buffer, from); 
    } 

    string(string&& other) 
     : buffer(other.buffer) 
    { 
     other.buffer = nullptr; // (*) 
    } 

    ~string() { 
     delete[] buffer; 
    } 

    char const* data() const { return buffer; } 
}; 

나는 data() 구성원이 동일하지 않은 이유를 보여줍니다 희망을 다음과 같이 string

훨씬 단순화 (불완전한) 버전을 볼 수 있었다. (*)으로 표시된 행을 생략 한 경우 main 끝에 두 번 내부 버퍼를 삭제합니다 (s에 한 번, s2에 한 번). buffer 포인터를 재설정하면 이러한 상황이 발생하지 않습니다.

3

std::string에는 자체 버퍼가 있습니다. 하나를 다른 것으로 옮긴 사실로 하나의 버퍼를 공유하지는 않습니다. s2을 초기화하면 s에서 버퍼를 넘겨 받아 해당 버퍼의 소유자가됩니다. s이 동일한 버퍼를 "소유"하지 못하도록하기 위해 단순히 s의 버퍼를 새로운 빈 버퍼로 설정합니다 (현재는 s이 담당합니다).

기술적으로도 참여 약간의 최적화가, 거기에 명시 적으로 비어 있거나 매우 작은 문자열에 할당있어 진정한 버퍼가 아니지만, 대신 std::string의 구현이 std::string의 메모리 자체의 일부를 사용할 가능성 . 이것은 일반적으로 STL에서 작은 문자열 최적화라고합니다.

s도 옮겨 졌으므로 코드에 대한 데이터 액세스가 불법입니다. 즉, 이 반환 할 수 있습니다.

2

당신은 사용하지 말아야 이동 된-에서 string 몇 가지 알려진 값으로 그 값을 교체하기 전에 :

라이브러리 코드는 인수에 유효한 값을 떠날 필요하지만 유형 또는 함수 문서를 제외하고, 그렇지 않으면된다 결과 인수 값에는 다른 제한 조건이 없습니다. 이것은 일반적으로 from 인수를 다시 사용하는 것을 피하는 것이 가장 현명하다는 것을 의미합니다. 다시 사용해야하는 경우, 그렇게하기 전에 알려진 값으로 다시 초기화하십시오.

라이브러리는 원하는 모든 것을 문자열에 붙일 수 있지만 빈 문자열로 끝날 가능성이 큽니다. 그것이 example from cppreference을 실행하는 것입니다. 그러나, 특히 이동 된 객체 내에서 어떤 것도 찾을 것으로 기대해서는 안됩니다.

관련 문제