简体   繁体   English

字符串的c_str()函数的C ++奇怪行为

[英]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. 我将项目从Visual Studio 06迁移到2010。这样做的时候,我在代码中观察到了这种现象。 I have a Get string function that look like this: 我有一个如下所示的Get string函数:

string GetTheStr() 
{ 
        return strSomeStdString; 
} 

Then there is another function that call above get function like this: 然后在get函数上方调用了另一个函数,如下所示:

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

the value of string pointed by ptrStr is "" ptrStr指向的字符串的值为“”

above code was working fine in visual studio 06 but not on visual studio 2010. 上面的代码在Visual Studio 06中工作正常,但在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? 谁能告诉我为什么上述行为在Visual Studio 2010中发生而在Visual Studio 06中却没有发生?

Thanks in advance :) 提前致谢 :)

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. 在无效情况下发生的情况是,GetTheStr()返回一个临时值,然后c_str()返回对其内部数据的引用,然后该临时范围超出范围,突然间您有一个悬挂的对存储的引用不再有效。 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. 当您将GetTheStr()的返回值分配给命名变量时,该变量仍然有效,并且其c_str()的结果仍指向有效数据。

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); 据我了解,整个语句都有临时生命( std::cout << GetTheStr().c_str() << endl;在技​​术上对我来说是有效的,因为lifteime需要在整个语句中持续使用,但效果很差因为它依赖生命的一个非常微妙的方面而写); 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. 如果您需要保留对对象内部数据的引用,那么始终最好保证有一个引用对象的命名变量,以确保包含对象的生存期超过其内部数据使用的生存期。

in simple words 简单来说

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

use the lifetime of str to keep the data "alive" 使用str的生命周期来保持数据“有效”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM