我最近惊讶地发现C ++中的临时变量被提升为具有完整的词法范围:
class Foo {
public:
Foo() {
std::cout << "A";
}
~Foo() {
std::cout << "B";
}
};
int main(void)
{
// Prints "ACB", showing the temporary being promoted to having lexical scope.
const Foo& f = Foo();
std::cout << "C";
return 0;
}
除了将临时分配给引用的可疑行为之外,这实际上工作正常(在VS2010和G ++ v4.1中测试)。输出为ACB
,清楚地显示临时对象已被提升为具有词法范围,并且仅在函数结束时被销毁(B
之后打印C
)。 / p>
其他临时变量的行为不是这样的:
int main(void)
{
// Prints "ACBD", showing that the temporary is destroyed before the next sequence point.
const int f = ((Foo(), std::cout << "C"), 5);
std::cout << "D";
return 0;
}
根据我的代码注释,这会打印ACBD
,显示临时变量一直保留到整个表达式完成评估(为什么在C
之前打印B
),但仍然被销毁在下一个序列点之前(为什么在B
之前打印D
)。 (这种行为是我认为C ++中的所有临时变量都有效的方式。我对之前的行为感到非常惊讶。)
有人可以解释一个临时被提升为具有这样的词汇范围的合法时间吗?
答案 0 :(得分:5)
绑定到常量左值引用或rvalue引用(因为C ++ 11)的临时值的生命周期被扩展到该引用的生命周期。在第二种情况下,您在作业的左侧没有引用,而是一个值,因此临时的生命周期不会延长。
参见C ++ 11标准的12.2 / 4和12.2 / 5:
有两种情况下,临时表在不同于完整表达结束时被摧毁。第一个上下文是调用默认构造函数来初始化数组的元素[...]
当引用绑定到临时时,第二个上下文是。绑定引用的临时对象或绑定引用的子对象的完整对象的临时对象在的生命周期内持续存在:[...]
“除了”后面的内容是不适用于这种情况的情况。