在回答了一些问题后,我今天构建了这个实验
struct A {
bool &b;
A(bool &b):b(b) { }
~A() { std::cout << b; }
bool yield() { return true; }
};
bool b = A(b).yield();
int main() { }
b
在通过动态初始化将其设置为 true
之前具有值 false
(由零初始化产生)。如果临时在 b
初始化完成之前被销毁,我们将打印 false
,否则打印 true
。
规范说临时在完整表达式结束时被销毁。这似乎与 b
的初始化无关。所以我想知道
- 规范是否允许实现在不同的运行中同时打印
false
和true
?
Clang 为上述打印 false
,而 GCC 打印 true
。这让我很困惑。我错过了一些定义订单的规范文本吗?
最佳答案
我认为它可以打印出真假,或者出于某种不相关的原因,什么都没有。
真假部分是(正如您所说),临时 A
对象的销毁相对于 b
的动态初始化没有顺序.
没有任何可能是因为 b
的初始化相对于 std::cout
的创建/初始化没有顺序;当您尝试销毁临时文件时,cout
可能尚未创建/初始化,因此尝试打印某些内容可能根本不起作用。 [编辑:这是 C++98/03 特有的,不适用于 C++11。]
编辑:至少我是这样看待序列的:
Edit2:在重读 §12.2/4(再次)之后,我再次更改了图表。 §12.2/4 说:
There are two contexts in which temporaries are destroyed at a different point than the end of the full expression. The first context is when an expression appears as an initializer for a declarator defining an object. In that context, the temporary that holds the result of the expression shall persist until the object’s initialization is complete. The object is initialized from a copy of the temporary; during this copying, an implementation can call the copy constructor many times; the temporary is destroyed after it has been copied, before or when the initialization completes.
我相信这个表达式是定义对象的声明器的初始化器,因此需要从表达式值的拷贝(在本例中为 true
)初始化对象,而不是直接从返回值。在 true
的情况下,这可能是没有区别的区别,但我认为现在的图表在技术上更准确。
这也很清楚(我认为)临时持有 true
确实 not 必须在完整表达式的末尾被销毁,所以我重新- 绘制图表以反射(reflect)这一点。
这部分在 C++0x/C++11 中消失了,所以我重新绘制了图表(再次)以显示两者之间的区别(以及这部分在 C+ 中变得多么简单+11)。
关于c++ - 初始化器究竟是什么时候被临时销毁的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5760866/