c++中string's c_str()函数的奇怪行为

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

本文关键字:函数 str string c++      更新时间:2023-10-16

我正在将我的项目从Visual Studio 06移动到2010。在这样做的过程中,我在代码中观察到了这种行为。我有一个Get字符串函数,看起来像这样:

string GetTheStr() 
{ 
        return strSomeStdString; 
} 

然后还有一个函数像这样调用上面的get函数:

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

ptrStr指向的string对象的值为"

上面的代码可以在visual studio 06中正常工作,但不能在visual studio 2010中工作。

然后我做了一些实验:

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

我想知道为什么最后一行没有工作。谁能告诉我为什么上面的行为发生在visual studio 2010而不是visual studio 06?

提前感谢:)

无效情况下发生的事情是GetTheStr()返回临时,然后c_str()返回对其内部数据的引用,然后临时超出范围,突然您有一个对存储不再有效的悬垂引用。当你将GetTheStr()的返回值赋值给一个命名变量时,该变量仍然存在,其c_str()的结果仍然指向有效数据。

临时的

生命周期在不同的实现中是不同的。我的理解是,整个语句的临时生命(std::cout << GetTheStr().c_str() << endl;在技术上是有效的,因为生命周期需要持续整个语句,但写得不好,因为它依赖于生命周期的一个非常微妙的方面);然而,根据我的理解,临时是否存在于该语句之外的范围的末尾是由实现定义的。我可能会因为这最后一段而受到嘲笑(尤其是那些对这个主题有更精确知识的人),但简单来说,当需要延长对象的生命周期时,写得好的代码应该更明确;如果需要保留对对象内部数据的引用,那么最好保证有一个命名变量引用对象,以确保包含对象的生存期超过其内部数据使用的生存期。

简写

std::string str = GetTheStr(); // -> this is a copy of strSomeStdString
const char* PtrCStr = str.c_str(); // -> str is still alive, ok
const char* PtrData = str.data(); // -> str is still alive, ok
const char*ptr = (char *)GetTheStr().c_str(); // -> pointer to a temporary, bad

使用str的生存期来保持数据"存活"