【问题标题】:Lifetime of C++ temporary extended to lexical when assigned to const& [duplicate]分配给 const& 时,C++ 临时扩展为词法的生命周期 [重复]
【发布时间】:2013-01-20 12:15:33
【问题描述】:

最近我惊讶地发现 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,清楚地表明临时对象已被提升为具有词法范围,并且仅在函数结束时被破坏(BC之后打印)。


其他临时变量不这样:

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,表明临时变量会一直保留到整个表达式完成评估(为什么CB 之前打印),但仍会在下一个序列点之前被销毁(为什么BD 之前打印)。 (这种行为是我认为 C++ 中所有临时变量的工作方式。我对之前的行为感到非常惊讶。)

谁能解释一下什么时候将临时对象提升为具有这样的词法范围是合法的?

【问题讨论】:

  • 仅当您将其绑定到第一个示例中的引用时。 (const&amp;&amp;&amp; 引用都有效)

标签: c++ scope lifetime


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 有趣。似乎编译器也会在这里应用一些智能,因为“f = (1, Foo())”也会导致提升。更复杂的代码不会,例如“F = identity(Foo())”。这里肯定有一个看似无害的重构会导致真正的行为改变的空间。不过感谢您的参考! :)
  • @pauldoo:不要将其视为促销。将其视为具有约束力。只要const reference 被绑定,它就会一直存在。
  • 请注意,它在标准中实际所说的并不是它要说的,也不是任何编译器实际实现的。实际行为更像是“当引用由临时对象初始化时,临时对象的生命周期会延长以匹配 that 引用的生命周期。”换句话说,这种生命周期的延长不是传递的,其他可能最终绑定到临时的引用(因为它们是用第一个引用初始化的)对其生命周期没有影响。
  • @JamesKanze:措辞上写着“[...] 在 the 参考 [...] 的生命周期内持续存在”。我想这里隐含的是它正在谈论临时绑定的引用
  • @AndyProwl 临时可以绑定到任意数量的引用。它的生命周期仅受在初始化表达式中使用它的引用影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
  • 2021-05-17
  • 1970-01-01
  • 2015-12-28
  • 2012-05-19
  • 1970-01-01
  • 2010-10-09
相关资源
最近更新 更多