13

I wonder if i misunderstood something: does a copy constructor from std::string not copy its content?

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

This will print "You will get into the IPC hell very soon!!" and it annoys me.

Is this the normal behavior of std::string? I read somewhere that it usually does a deep copy.

However, this works as expected:

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

It copies the contents into the new string.

pmr
  • 58,701
  • 10
  • 113
  • 156
  • Try modifying `str2` in your first example (e.g. `str2[0] = 'B';`) and *then* comparing the `c_str()` values. – Angew is no longer proud of SO May 17 '13 at 08:48
  • For what it's worth, GCC 4.7 has the same behaviour both in C++03 and C++11 modes (and @Angew's suggestion indeed yields different `c_str()` values). – syam May 17 '13 at 08:49
  • Appearently it allocates a new buffer after the edit u sugested @Angew . So it seems to be some sort of "optimization" ... it costed us several hour of work to find that problem.*sigh* – Philipp Michalski May 17 '13 at 08:53

2 Answers2

14

It is entirely possible that your string implementation uses copy-on-write which would explain the behavior. Although this is less likely with newer implementations (and non-conforming on C++11 implementations).

The standard places no restriction on the value of the pointer returned by c_str (besides that it points to a null-terminated c-string), so your code is inherently non-portable.

pmr
  • 58,701
  • 10
  • 113
  • 156
  • Why is COW less likely with newer implementations. – user93353 May 17 '13 at 08:48
  • 2
    @user93353 COW is not possible to implement if you want to be C++11 conforming: http://stackoverflow.com/questions/12199710/legality-of-cow-stdstring-implementation-in-c11 – pmr May 17 '13 at 08:50
  • @user93353: COW can severily decrease performance in multithreaded environments. For that reason it has lost a lot of popularity (and been banned in C++11). – Grizzly May 17 '13 at 08:52
  • 1
    @user93353 Lots of people disagree with respect to multi-threading. There are also move semantics, which handle a lot of classic cases where COW used to be helpful. – pmr May 17 '13 at 08:53
  • Yepp it like you said. Good to know NOW ... Thanks! I will accept your answer later, i ll just wait if somebody else has an something interesting to say about this. – Philipp Michalski May 17 '13 at 08:56
  • As I said in another comment, GCC 4.7 in C++11 mode has the same behaviour. Looking at the sources `/usr/include/c++/4.7/bits/basic_string.h` it is indeed COW (meh what about C++11 conformance?...). – syam May 17 '13 at 08:57
  • 2
    @syam This is considered a defect and might change: http://stackoverflow.com/questions/12520192/is-stdstring-refcounted-in-gcc-c11 and the linked thread. – pmr May 17 '13 at 09:01
5

std::string implementation in your compiler must be reference counted. Change one of the strings and then check the pointers again - they would be different.

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.

These are 3 excellent articles on reference counted strings.

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

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

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

user93353
  • 13,733
  • 8
  • 60
  • 122