std::string конструктор за копиране НЕ е дълбоко в GCC 4.1.2?

Чудя се дали не съм разбрал нещо погрешно: дали конструкторът за копиране от std::string не копира съдържанието му?

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!!");

Това ще отпечата "Вие ще влезете в IPC ада много скоро!!" и това ме дразни.

Това ли е нормалното поведение на std::string? Четох някъде, че обикновено прави дълбоко копиране.

Това обаче работи според очакванията:

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!");

Той копира съдържанието в новия низ.


person Philipp Michalski    schedule 17.05.2013    source източник
comment
Опитайте да промените str2 в първия си пример (напр. str2[0] = 'B';) и след това да сравните стойностите c_str().   -  person Angew is no longer proud of SO    schedule 17.05.2013
comment
Колкото и да си струва, GCC 4.7 има същото поведение както в режимите C++03, така и в C++11 (и предложението на @Angew наистина дава различни c_str() стойности).   -  person syam    schedule 17.05.2013
comment
Очевидно той разпределя нов буфер след редакцията, предложена от @Angew. Така че изглежда е някакъв вид оптимизация ... струва ни няколко часа работа, за да открием този проблем.*въздишка*   -  person Philipp Michalski    schedule 17.05.2013


Отговори (2)


Напълно възможно е вашето string внедряване да използва копиране при запис, което би обяснило поведението. Въпреки че това е по-малко вероятно с по-нови реализации (и несъответстващи на C++11 реализации).

Стандартът не поставя ограничение върху стойността на указателя, върнат от c_str (освен това той сочи към c-низ с нулев край), така че вашият код по своята същност е непреносим.

person pmr    schedule 17.05.2013
comment
Защо COW е по-малко вероятно с по-нови реализации. - person user93353; 17.05.2013
comment
@user93353 COW не е възможно да се внедри, ако искате да отговаряте на C++11: stackoverflow.com/questions/12199710/ - person pmr; 17.05.2013
comment
@user93353: COW може сериозно да намали производителността в многонишкови среди. Поради тази причина е загубил много популярност (и е забранен в C++11). - person Grizzly; 17.05.2013
comment
@user93353 Много хора не са съгласни по отношение на многопоточността. Има и семантика на движение, която се справя с много класически случаи, в които COW е бил полезен. - person pmr; 17.05.2013
comment
Да, както казахте. Добре е да знам СЕГА ... Благодаря! Ще приема отговора ви по-късно, просто ще изчакам, ако някой друг има да каже нещо интересно за това. - person Philipp Michalski; 17.05.2013
comment
Както казах в друг коментар, GCC 4.7 в режим C++11 има същото поведение. Гледайки източниците /usr/include/c++/4.7/bits/basic_string.h, това наистина е COW (ми какво ще кажете за съответствието на C++11?...). - person syam; 17.05.2013
comment
@syam Това се счита за дефект и може да се промени: stackoverflow.com/questions/12520192/ и свързаната нишка. - person pmr; 17.05.2013

std::string внедряването във вашия компилатор трябва да се брои препратка. Променете един от низовете и след това проверете указателите отново - те ще бъдат различни.

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.

Това са 3 отлични статии за преброени низове.

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

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

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

person user93353    schedule 17.05.2013
comment
Направих, както посочих в коментара си за самия въпрос и подобно на казаното по-горе: прави копие при запис! - person Philipp Michalski; 17.05.2013