我有一个定义如下的方法:
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:我们每周构建一次代码。我上周提交代码时测试了这个,事情还不错。所以,我真的想知道我在这里可能会缺少什么。
感谢, 帕。
答案 0 :(得分:9)
第一个是未定义的行为,临时returnStringMethod()
仅在尾随;
之前有效,因此内部字符串(由c_str()
返回)被销毁,所以你离开了一个悬垂的指针。
第二个版本是有效的,因为str
在其范围结束时将被销毁,其范围与ptr
相同(至少在您的示例中)。
例如,以下内容也是错误的:
const char * ptr = NULL;
{
std::string str = returnStringMethod();
ptr = str.c_str();
}
在}
之后,ptr
不再有效。
答案 1 :(得分:3)
returnStringMethod
的返回值是一个临时字符串,其生命周期与表达式本身绑定;这意味着,在std::string
初始化c_str
后,您ptr
上的const char * ptr = returnStringMethod ().c_str ()
将被销毁。
这样做的含义是ptr
已初始化的值,指向不再可访问的内存。
在后一种情况下,将returnStringMethod
的返回值分配给std::string str
,您将获得一个生命周期绑定到当前范围的副本。将str.c_str ()
的值分配给ptr
,只要str
有效,就会有效。
答案 2 :(得分:3)
const char * ptr = returnStringMethod().c_str();
在上面一行中,一个临时字符串由函数返回,该函数很快就会超出范围。 (并且调用析构函数并释放内存)
在更高版本中,您可以创建字符串的本地副本,从而定义行为。
您还可以使用以下
const std::string &str = returnStringMethod();
const char * ptr = str.c_str();
使用const引用会延长临时变量的生命周期,直到引用在范围内,并且不会有(明确的)不需要的副本。
答案 3 :(得分:1)
您正在返回(临时)副本以及执行c_str()的位置。
当临时消失时,c_str()返回的char *变为无效。