2011-04-22 59 views
2

这是明确定义的行为吗?临时表达行为

const char* p = (std::string("Hello") + std::string("World")).c_str(); 
std::cout << p; 

我不确定。原因是什么?

回答

6

不,这是未定义的行为。临时文件std::string和临时文件operator+返回的临时文件只有在您的const char*(完整表达式结束)初始化结束时才会生效。然后它们被销毁并且指向不确定的记忆。

+2

每个人都只赞@Johannes(尽管@Prasoon引用了参考文献)。非常不公平。 :P – Nawaz 2011-04-22 15:29:08

+1

@Nawaz:你能做什么,Johannes是这里的名人...... – fredoverflow 2011-04-22 15:32:09

+1

@Nawaz:引用Herb Sutter,“这个标准不是真正的人们阅读的教程。”除非有人明确要求引用规范或主题如此技术性以至于需要引用,否则最好将规范留给答案。只是复制一段没有解释的段落(什么是“定义一个对象的声明的初始化器”?)并不是特别有用。 – 2011-04-22 15:55:46

2

无行为是不确定的,因为p指向std::cout << p;

创建持有std::string("Hello") + std::string("World")临时释放存储空间。 C风格的字符串然后从该对象中回收。在表达式结尾处,临时被销毁,离开p指向一个释放存储。使用p然后调用未定义的行为。

12.2/4说

存在其中的临时被在不同的点比全表达式的结尾破坏两个上下文。第一个上下文是当表达式作为定义对象的声明符的初始化符出现时。在这种情况下,保留表达式结果的临时表将一直保留,直到对象的初始化完成为止 。
....

+2

您突出显示的位并不明显。包含用作初始值设定项的表达式的临时数据类型为'const char *'类型的临时类型,其中包含来自'c_str()'的返回值。你所引用的内容说* *临时存在,直到初始化完成,它不会说表达式中的所有临时对象(包括字符串)都会一直存在,直到初始化完成... – 2011-04-22 18:36:37

+0

...尽管我认为这暗示了其他地方,也许是关于临时被破坏的创造逆序的东西?不确定。 – 2011-04-22 18:43:43

1

因为缺少分号的它不会编译:

const char* p = (std::string("Hello") + std::string("World")).c_str(); //<< important here 
std::cout << p; 

现在的规则适用,临时在其使用的表达,这是分号结束时删除。所以你有一个指向删除内存的指针,导致未定义的行为。