Consider the following example:
int main()
{
string x = "hello";
//copy constructor has been called here.
string y(x);
//c_str return const char*, but this usage is quite popular.
char* temp = (char*)y.c_str();
temp[0] = 'p';
cout << "x = " << x << endl;
cout << "y = " << y << endl;
cin >> x;
return 0;
}
Run it on visual studio compiler and on g++.
When I did so, I got two different results.
in g++:
x = pello
y = pello
In visual studio 2010:
x = hello
y = pello
The reason for the diff is most likely that g++ std::string implementation uses COW (copy on write) techniques and visual studio does not.
Now the C++ standard (page 616 table 64) states with regards to string copy constructor
basic_string(const basic_string& str):
effects:
data()
should "points at the ?rst element of an allocated copy of the array whose ?rst element is pointed at by str.data()
"
Meaning COW is not allowed (at least to my understanding).
How can that be?
Does g++ meets std::string
C++11 requirements?
Before C++11 this did not pose a big problem since c_str
didn't return a pointer to the actual data the string object holds, so changing it didn't matter. But after the change this combination of COW + returning the actual pointer can and breaks old applications (applications that deserve it for bad coding but nevertheless).
Do you agree with me? If yes, can something be done? Does anyone have an idea about how to go at it in a very big old code environments (a clockwork rule to catch this would be nice).
Note that even without casting the constness away, one might cause invalidation of a pointer by calling c_str, saving the pointer and then calling non-const method (which will cause write).
Another example without casting the constness away:
int main()
{
string x = "hello";
//copy constructor has been called here.
string y(x);
//y[0] = 'p';
//c_str return const char*, but this usage is quite popular.
const char* temp = y.c_str();
y[0] = 'p';
//Now we expect "pello" because the standart says the pointer points to the actual data
//but we will get "hello"
cout << "temp = " << temp << endl;
return 0;
}
See Question&Answers more detail:os