2013-05-17 23 views
13

Zastanawiam się, czy coś źle zrozumiałem: czy konstruktor kopii od std::stringnie skopiuj jego zawartość?Konstruktor kopii std :: string NOT in GCC 4.1.2?

string str1 = "Hello World"; 
string str2(str1); 

if(str1.c_str() == str2.c_str()) // Same pointers! 
    printf ("You will get into the IPC hell very soon!!"); 

To wydrukuje "Wkrótce wejdziesz do piekła IPC!" i to mnie denerwuje. To jest normalne zachowanie std::string? Czytałem gdzieś, że zwykle robi głęboką kopię.

Jednak to działa zgodnie z oczekiwaniami:

string str3(str1.c_str()); 

if(str1.c_str() == str3.c_str()) // Different pointers! 
    printf ("You will get into the IPC hell very soon!!"); 
else 
    printf ("You are safe! This time!"); 

kopiuje zawartość do nowego łańcucha.

+0

Spróbuj zmodyfikować 'str2' w pierwszym przykładzie (np' słowo2 [0] = 'B'; ') * a *, a następnie porównanie' c_str () 'wartości. – Angew

+0

Dla tego, co jest warte, GCC 4.7 ma takie samo działanie zarówno w C++ 03, jak i C++ 11 (i sugestia @ Angewa rzeczywiście daje różne wartości 'c_str()'). – syam

+0

Najprawdopodobniej przydziela nowy bufor po skończonej próbie @Angew. Wygląda więc na jakąś "optymalizację" ... kosztowało nas to kilka godzin pracy, aby znaleźć ten problem. * Wzdychanie * –

Odpowiedz

14

Jest całkowicie możliwe, że twoja implementacja string wykorzystuje kopiowanie przy zapisie, które wyjaśniałoby zachowanie. Chociaż jest to mniej prawdopodobne w przypadku nowszych implementacji (i niezgodnych z implementacjami C++ 11).

Standard nie umieszcza żadnych ograniczeń na wartości wskaźnika zwróconego przez c_str (poza tym, że wskazuje na zakończony znakiem N ciąg znaków), więc twój kod jest z natury nieprzenośny.

+0

Dlaczego COW jest mniej prawdopodobne w przypadku nowszych implementacji. – user93353

+2

@ user93353 COW nie można wprowadzić, jeśli chcesz spełniać wymagania C++ 11: http://stackoverflow.com/questions/12199710/legality-of-cow-stdstring-implementation-in-c11 – pmr

+0

@ user93353: COW może znacznie zmniejszyć wydajność w środowiskach wielowątkowych. Z tego powodu stracił popularność (i został zbanowany w C++ 11). – Grizzly

5

std::string implementacja w kompilatorze musi być zliczana jako odniesienie. Zmień jeden z ciągów, a następnie sprawdź wskaźniki jeszcze raz - byłyby inne.

string str1 = "Hello World"; 
string str2(str1); 

if(str1.c_str() == str2.c_str()) // Same pointers! 
    printf ("You will get into the IPC hell very soon!!"); 

str2.replace(' ',','); 

// Check again here. 

Są to 3 doskonałe artykuły na temat odnośników zliczonych ciągów.

http://www.gotw.ca/gotw/043.htm

http://www.gotw.ca/gotw/044.htm

http://www.gotw.ca/gotw/045.htm

+0

Zrobiłem, jak wskazałem w moim komentarzu do samego pytania i jego jak wyżej powiedziałem: robi kopię na piśmie! –

Powiązane problemy