R值和L值的输出不同.为什么?

Leo*_*sky 1 c++ rvalue-reference perfect-forwarding c++11

有人可以向我解释为什么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;
}
Run Code Online (Sandbox Code Playgroud)

输出(gcc48和clang32相同):

2
123
2
003
Run Code Online (Sandbox Code Playgroud)

回答

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

当临时向量初始化r-value-ref成员变量时rv.ct,临时生命周期不会扩展,因为有一个特殊的例外:[class.temporary] p5:"临时绑定到构造函数的ctor-initializer中的引用成员(12.6.2)一直持续到构造函数退出."

Joh*_*itb 7

因为您的会员只是一个参考.在第二种情况下,它引用的对象在局部rv变量的定义完成后已经死了.所以后来的访问cout是未定义的行为.

  • @hvd对了.实际上,在class.temporary中没有区别.该子句指的是表达式直接具有该属性的情况.(当标准中的文字说"创建了prvalue临时..."时,rvalue直接携带该临时属性).其他规则引用临时*对象*而不是以这种方式标记的表达式,因此需要始终仔细阅读封闭的上下文以了解其含义(恕我直言,规范在这里非常差,可以更加清晰,请参阅http: //www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299). (3认同)