【问题标题】:Will a reference bound to a function parameter prolong the lifetime of that temporary?绑定到函数参数的引用会延长该临时变量的生命周期吗?
【发布时间】:2012-04-28 18:14:21
【问题描述】:

我有这个代码(简化版):

const int& function( const int& param )
{
     return param;
}

const int& reference = function( 10 );
//use reference

我不能完全确定 C++03 标准 $12.2/5 措辞的程度

引用绑定到的临时对象或作为临时对象绑定的子对象的完整对象的临时对象在引用的生命周期内持续存在...

适用于此。

上面代码中的reference 变量是有效的还是悬空的?调用代码中的引用是否会延长临时作为参数传递的生命周期?

【问题讨论】:

    标签: c++ reference object-lifetime function-parameter


    【解决方案1】:

    full-expression 是不是另一个表达式的子表达式的表达式。在这种情况下,包含调用 function( 10 ) 的完整表达式是赋值表达式:

    const int& reference = function( 10 );
    

    为了使用参数10 调用function,为临时整数对象10 创建一个临时常量引用对象。临时整数和临时 const-reference 的生命周期通过赋值扩展,因此尽管赋值表达式有效,但尝试使用 reference 引用的整数是未定义行为,因为 reference 不再引用活动对象。

    我认为 C++11 标准澄清了这种情况:

    引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在,但以下情况除外:

    ...

    ——在函数调用 (5.2.2) 中临时绑定到引用参数会一直持续到包含调用的完整表达式完成为止。

    “引用绑定到的临时...在引用的生命周期内持续存在”。在这种情况下,引用的生命周期在赋值表达式的末尾结束,临时整数的生命周期也是如此。

    【讨论】:

      【解决方案2】:

      从 C++11 的观点来看,函数返回的引用不是临时的:

      12.12.1 类类型的临时对象在各种上下文中创建:将引用绑定到纯右值(8.5.3),返回 prvalue (6.6.3),创建 prvalue (4.1, 5.2.9, 5.2.11, 5.4) 的转换,抛出异常 (15.1), 进入一个处理程序(15.3),并在一些初始化(8.5)。

      返回引用的函数不会返回纯右值(“纯右值”),因此它不是临时的。 这似乎很自然:编译器无法管理引用对象的生命周期,这是程序员的责任

      因此,编译器不为 const int& 引用提供任何提升时间保证,因为它不受临时限制。

      【讨论】:

      • ... 这是 C++11 修复 C++03 模棱两可的措辞的一个地方,应该采取追溯应用的修复。
      【解决方案3】:

      这部分很重要

      引用绑定的临时对象

      在这种情况下,参数是绑定到临时的,调用后会被销毁。

      你不能通过传递引用来进一步延长生命周期。

      【讨论】:

      • 你不能否认他的reference是临时绑定的。实际上有几个引用绑定到临时。该标准在这里措辞非常糟糕。当然,目的是延长生命周期以匹配使用实际临时初始化的引用。遗憾的是,这并不是标准所说的。
      • @JamesKanze:我同意措辞不是很精确,但话虽如此,使用单独的编译模型,编译器不可能知道应该延长临时的生命周期函数完成后在调用点。编译器不可能知道返回的引用是否绑定到与参数相同的对象或任何其他对象(即const int& function( const int& ) { static int i = 0; return i; }
      • 这个答案没有解决任何问题......并且临时在语句末尾的分号处被销毁,而不是在调用之后立即销毁。
      • @Potatoswatter - 调用后我没有说立即,而是临时的生命周期取决于参数的生命周期。
      • @BoPersson 参数生命周期确实在函数结束时结束。如果你的意思是临时的生命周期取决于 argument 的生命周期,那是真的,但是临时的和参数是相同的,所以它是空洞的。更清楚地说,函数调用对其参数的生命周期没有影响。编辑:我不是反对者。
      【解决方案4】:

      这将编译,但您最终会得到一个悬空引用。 paramfunction 返回后被释放。

      1. 函数是通过引用临时匿名对象调用的
      2. 函数返回引用
      3. 现在该函数已返回临时参数已释放
      4. 随着对象被破坏,引用现在悬空

      如果您将其设为非常量,那么它就不会编译,因为您无法将非常量引用传递给匿名对象。

      【讨论】:

      • param 不是在作业结束时销毁了吗? “临时对象在评估完整表达式 (1.9) 的最后一步时被销毁,该完整表达式 (从词法上) 包含它们的创建点。”
      猜你喜欢
      • 1970-01-01
      • 2012-07-17
      • 2012-09-15
      • 2015-05-03
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2019-01-06
      相关资源
      最近更新 更多