Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
272 views
in Technique[技术] by (71.8m points)

stdstring - C++ strange behavior with string's c_str() function

I am moving my project from Visual Studio 06 to 2010. While doing so, I have observed this behavior in my code. I have a Get string function that look like this:

string GetTheStr() 
{ 
        return strSomeStdString; 
} 

Then there is another function that call above get function like this:

const char* ptrStr = (char *)GetTheStr().c_str();

the value of string pointed by ptrStr is ""

above code was working fine in visual studio 06 but not on visual studio 2010.

Then I tried few experiments:

std::string str = GetTheStr(); // -> value inside str displayed correctly
const char* PtrCStr = str.c_str(); // -> value pointed by PtrCStr displayed correctly
const char* PtrData = str.data(); // -> value pointed by PtrData displayed correctly
const char* ptr = (char *)GetTheStr().c_str(); // -> value pointed by ptr NOT displayed correctly

I am wondering why last line didn't work. Can anyone please tell me why above behavior happen in visual studio 2010 but not on visual studio 06?

Thanks in advance :)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

What's happening in the invalid case is that GetTheStr() is returning a temporary, then c_str() is returning a reference to its internal data, then the temporary goes out of scope and suddenly you have a dangling reference to storage that is no longer valid. When you assign the returned value of GetTheStr() to a named variable, the variable is still alive and the result of its c_str() is still pointing to valid data.

Lifetimes of temporaries is something that varies between implementations. It is my understanding that a temporary lives for the entire statement (std::cout << GetTheStr().c_str() << endl; is technically valid to my understanding because the lifteime is required to last for the entire statement, but poorly written because it is relying on a very subtle aspect of lifetime); however, whether a temporary lives beyond that statement to the end of the scope or not is, to my understanding, implementation-defined. I'm probably going to be pilloried for this last paragraph (especially by people with more precise knowledge on the topic), but the short story is that well written code should be more explicit when the lifetime of an object needs to be extended; if you need to retain a reference to the internal data of an object, then it's always best to guarantee that there is a named variable referring to the object to ensure that the containing object's lifetime exceeds the lifetime of the usage of its internal data.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...