【问题标题】:Output is different for R-value and L-value. Why?R值和L值的输出不同。为什么?
【发布时间】:2012-09-01 09:28:33
【问题描述】:

有人可以向我解释为什么 R 值的输出与 L 值不同吗?

#include <iostream>
#include <vector>
using namespace std;

template<typename Ct>
struct  ct_wrapper {
    Ct&& ct; // R or L ref
    explicit ct_wrapper(Ct&& ct) 
      : ct(std::forward<Ct>(ct)) { std::cout <<  this->ct[1];};
};

int main() {

    // L-val
    vector<int> v{1,2,3};
    ct_wrapper<vector<int>&> lv(v);
    cout << endl << lv.ct[0] << lv.ct[1] << lv.ct[2] << endl;

    // R-val
    ct_wrapper<vector<int>&&> rv(vector<int>{1,2,3});
    cout << endl << rv.ct[0] << rv.ct[1] << rv.ct[2] << endl;
}

输出(gcc48 和 clang32 相同):

2
123
2
003

回答

它在我与 Johannes Schaub 的聊天中被埋没了,所以我把它放在这里。

当临时向量初始化 r-value-ref 成员变量rv.ct 时,临时生命周期没有延长,因为有一个特殊的例外:[class.temporary]p5:“在构造函数的ctor-中临时绑定到引用成员-初始化程序 (12.6.2) 一直存在,直到构造函数退出。”

【问题讨论】:

    标签: c++ c++11 rvalue-reference perfect-forwarding


    【解决方案1】:

    因为您的会员只是一个参考。在第二种情况下,它引用的对象在本地 rv 变量的定义完成后已经死了。因此,cout 中的后续访问是未定义的行为。

    【讨论】:

    • +1(以及所有其他),但我仍然感到困惑。我认为当临时绑定到 r-value ref 时,它的生命周期会延长到 r-value 变量的生命周期。不?我们还有rv.ct
    • @LeonidVolnitsky 有一个特殊的例外(因为否则编译器不可能做到这一点):[class.temporary]p5:“临时绑定到构造函数的ctor中的引用成员-初始化程序(12.6.2)一直存在,直到构造函数退出。” (我要说的是引用不是绑定到临时的,而是对临时的引用,但我在标准中看不到这种区别。)
    • @hvd 对。实际上,在子句 class.temporary 中并没有区分。该子句指的是表达式直接具有该属性的情况。 (当标准中的文本说“创建了一个纯右值临时......”时,右值直接带有该临时属性)。其他规则指的是临时 objects 而不是以这种方式标记的表达式,因此需要始终仔细阅读封闭上下文以了解其含义(恕我直言,这里的规范很差,可以做很多更清晰,请参阅open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299)。
    • 感谢您的澄清,很高兴知道我不是唯一一个弄糊涂的人。 :) 所以它毕竟更简单,初始化器std::forward&lt;Ct&gt;(ct) 不是临时的(在 [class.temporary] 的上下文中)。
    • @LeonidVolnitsky:这真的没有那么令人困惑:引用变量是ct,它只在构造函数的持续时间内存在。
    【解决方案2】:

    您的程序有未定义的行为,因为您正在访问一个悬空引用。临时向量在其出现的完整表达式结束时被销毁,但您仍保留对它的引用。

    【讨论】:

      【解决方案3】:

      在右值情况下,您将临时绑定到引用。当您到达最后一个输出语句时,它已经消失了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-31
        • 2016-07-02
        • 2012-06-29
        • 1970-01-01
        • 1970-01-01
        • 2017-02-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多