2

我最近很惊讶地发现 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)。


其他临时变量的行为不是这样:

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++ 中所有临时变量的工作方式。我对之前的行为感到非常惊讶。)

有人可以解释一下何时将临时提升为具有这样的词法范围是合法的吗?

4

1 回答 1

5

绑定到常量左值引用或右值引用(自 C++11 起)的临时对象的生命周期延长至该引用的生命周期。在第二种情况下,赋值左侧没有引用,而是一个值,因此临时的生命周期不会延长。

请参阅 C++ 11 标准的 12.2/4 和 12.2/5:

在两种情况下,临时对象在与完整表达式结束时不同的点被销毁。第一个上下文是调用默认构造函数来初始化数组元素时 [...]

第二个上下文是引用绑定到一个临时的. 引用绑定到的临时对象或引用绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在,除了:[...]

“例外”之后的情况不适用于本案。

于 2013-02-05T14:27:51.100 回答