我有一个定义如下的方法:
const std::string returnStringMethod()
{
std::string myString;
// populate myString
return myString;
}
现在,在调用者中,我正在做这样的事情:
const char * ptr = returnStringMethod().c_str();
正如我所看到的,这返回了一些我没想到的截断字符串。然而,以下工作正常:
std::string str = returnStringMethod();
const char * ptr = str.c_str();
有人可以帮我理解这里发生了什么吗? .
PS:我们每周构建一次代码。我上周提交代码时对此进行了测试,一切都很好。所以,我真的很想知道我在这里可能会错过什么。
谢谢, 帕万。
第一个是未定义的行为,临时
returnStringMethod()
仅在尾随 ;
之前有效,因此内部字符串(由 c_str()
返回)被销毁,因此留下了一个悬空指针。
第二个版本是有效的,因为
str
将在其范围结束时被销毁,并且其范围与 ptr
相同(至少在您的示例中)。
例如,以下内容也将是错误的:
const char * ptr = NULL;
{
std::string str = returnStringMethod();
ptr = str.c_str();
}
}
之后,ptr
不再有效。
const char * ptr = returnStringMethod().c_str();
在上面的行中,函数返回一个临时字符串,该字符串很快就会超出范围。 (调用析构函数并释放内存)
在更高版本中,您会创建字符串的本地副本,从而定义行为。
您还可以使用以下
const std::string &str = returnStringMethod();
const char * ptr = str.c_str();
使用 const 引用会延长临时变量的寿命,直到引用在范围内并且不会有(显式的)不需要的副本。
returnStringMethod
的
返回值是一个临时字符串,其生命周期与表达式本身绑定;这意味着您调用
std::string
的 c_str
将在 ptr
中初始化 const char * ptr = returnStringMethod ().c_str ()
后立即被销毁。
这意味着
ptr
已初始化的值指向不再可访问的内存。
在后一种情况下,将
returnStringMethod
的返回值分配给 std::string str
,您将拥有一个其生命周期绑定到当前作用域的副本。因此,只要 str.c_str ()
还活着,将 ptr
的值分配给 str
就有效。
您将返回一个(临时)副本,这就是您执行 c_str() 的地方。
当临时消失时,c_str() 返回的 char * 变得无效。