代码:
stringstream ss("012345678901234567890123456789012345678901234567890123456789");
一些文章说由于ss.str返回临时对象而导致后续使用是错误的,并且在调用之前会被破坏.c_str();
const char* cstr2 = ss.str().c_str();
但我运行的例子,没有问题?怎么理解?
答案 0 :(得分:5)
但我运行这个例子,没有问题吗?
事实上,表达式没有错:
const char* cstr2 = ss.str().c_str();
ss.str()
返回的临时(复制)对象的存活时间足够长,可以让您获得c_str()
的基础c字符串。
当然,在表达式结束时,您将有一个const char
指针指向可能解除分配的对象(这在很大程度上取决于std::basic_string
实现)。
因此,这可能不是一个好主意。你应该做的是:
auto x = ss.str();
const char* cstr2 = x.c_str();
上面的代码不会给你带来任何麻烦,因为str()
的返回值现在被复制/不再是临时的,并且对x.c_str()
的访问将为你提供一个有效的指针
答案 1 :(得分:4)
首先,重要的是要了解尝试使用悬空指针并不是保证以任何明显的方式失败。它似乎经常“工作”,因为它可能会崩溃。
其次,是的,该代码无效,您不应该这样做。 stringstream的生命周期并不重要,因为std::stringstream::str()
按值返回 (即内部缓冲区的 copy ),但是你仍然需要使用该字符串在你可以使用它的C字符串指针之前超出范围。
答案 2 :(得分:3)
又一个精彩的C ++地雷。
基本上,你的指针引用了一个内存块(C字符串),它引用了当你进行双重操作时流中的任何内容的临时副本(字符串)。
str()返回一个临时对象。
临时物品的预期寿命相当短。有人要么立即引用它们(例如string& s = ss.str()
),要么在它们出生的声明结束时死亡。
但是,编译器允许通过c_str()获取对同一内存块的引用,但间接引用,因此它在编译器的雷达下飞行。太遗憾了。
所以你的指针确实在c_str得到它的时候是有效的,但只要你在普通的旧C中做了类似的事情就可以了:
const char * cstr2;
{
char ss_str[100]; // str() return value is dynamically created
char * c_str = &ss_str_[10]; // c_str() takes a reference to some part of it
cstr2 = c_str; // cstr2 takes an indirect reference to str() ret. val.
} // compiler pulls the plug on str() ret. val.
所以,在这个声明结束之后,c_str已经引用了返回的字符串str()的尸体。
现在,由于临时对象已在堆栈上分配,因此您可能永远不会注意到该问题。对象释放本身可能不会修改已失效的字符串值,但只要编译器重复使用此位堆栈,proverbial guru就会有一些东西需要冥想。