这是明确定义的行为吗?临时表达行为
const char* p = (std::string("Hello") + std::string("World")).c_str();
std::cout << p;
我不确定。原因是什么?
这是明确定义的行为吗?临时表达行为
const char* p = (std::string("Hello") + std::string("World")).c_str();
std::cout << p;
我不确定。原因是什么?
不,这是未定义的行为。临时文件std::string
和临时文件operator+
返回的临时文件只有在您的const char*
(完整表达式结束)初始化结束时才会生效。然后它们被销毁并且指向不确定的记忆。
无行为是不确定的,因为p
指向std::cout << p;
创建持有std::string("Hello") + std::string("World")
临时释放存储空间。 C风格的字符串然后从该对象中回收。在表达式结尾处,临时被销毁,离开p
指向一个释放存储。使用p
然后调用未定义的行为。
12.2/4说
存在其中的临时被在不同的点比全表达式的结尾破坏两个上下文。第一个上下文是当表达式作为定义对象的声明符的初始化符出现时。在这种情况下,保留表达式结果的临时表将一直保留,直到对象的初始化完成为止 。
....
您突出显示的位并不明显。包含用作初始值设定项的表达式的临时数据类型为'const char *'类型的临时类型,其中包含来自'c_str()'的返回值。你所引用的内容说* *临时存在,直到初始化完成,它不会说表达式中的所有临时对象(包括字符串)都会一直存在,直到初始化完成... – 2011-04-22 18:36:37
...尽管我认为这暗示了其他地方,也许是关于临时被破坏的创造逆序的东西?不确定。 – 2011-04-22 18:43:43
因为缺少分号的它不会编译:
const char* p = (std::string("Hello") + std::string("World")).c_str(); //<< important here
std::cout << p;
现在的规则适用,临时在其使用的表达,这是分号结束时删除。所以你有一个指向删除内存的指针,导致未定义的行为。
我最近读了这本优秀的书http://www.amazon.co.uk/Gotchas-Avoiding-Addison-Wesley-Professional-Computing/dp/0321125185/ref,如果我正确地记得,这几乎是其中的一个例子。
我相信从c_str
返回的数据只有在返回它的字符串对象是活的时才有效。您的示例中的字符串对象只在表达式的持续时间内有效。
每个人都只赞@Johannes(尽管@Prasoon引用了参考文献)。非常不公平。 :P – Nawaz 2011-04-22 15:29:08
@Nawaz:你能做什么,Johannes是这里的名人...... – fredoverflow 2011-04-22 15:32:09
@Nawaz:引用Herb Sutter,“这个标准不是真正的人们阅读的教程。”除非有人明确要求引用规范或主题如此技术性以至于需要引用,否则最好将规范留给答案。只是复制一段没有解释的段落(什么是“定义一个对象的声明的初始化器”?)并不是特别有用。 – 2011-04-22 15:55:46