-->

它是有效的绑定在C ++ 11的右值非const左值引用?(修改)(Is it valid to b

2019-09-02 13:53发布

我知道在C ++ 03的一个非const引用不能绑定到右值。

T& t = getT(); 是无效的,在C + + 11,我们可以这样做: T&& t = getT(); 但对于上面的代码,应在C ++ 11的工作?

我测试了以下VS11代码:

 Foo getFoo() {
  return Foo();
}

void fz(Foo& f) {
}

int getInt() {
  return int();
}

void iz(int& i) {
}

int main() {
  {
    Foo& z = getFoo(); //ok
    fz(getFoo()); //ok

    int& z2 = getInt(); //error: initial value of reference to non-const must be an lvalue
    iz(getInt()); //same as above
  }
}

Foo是一个自定义类,我不明白为什么前两行compiles.The临时通过引用z在主内范围的结束被破坏。 有没有标准说这事?

class Foo {
public:
  Foo() {
    std::cout << "constructed\n";
  }
  ~Foo() {
    std::cout << "destructed\n";
  }
};

我刚才看到一个类似的问题: 一个VS2010的错误? 允许绑定非const引用到右值,甚至没有一个警告?

Answer 1:

应在C ++ 11的工作?

不,它不应该。

Foo是一个自定义类,我不明白为什么前两行编译

它编译只能用MSVC。 MSVC具有(可以说是有用的) 编译器扩展 ,其允许结合用户定义类型的左值到右值,但标准本身禁止此。 见,例如, 这个活生生的例子 ,如果GCC 4.7.2拒绝编译代码。

有没有标准说这事?

的确如此。 每一段的C ++ 11标准的8.5.3 / 5:

键入“A参考cv1 T1 ”是通过类型“的表达初始化cv2 T2 ”,如下所示:

- 如果参考是一个左值参考和初始化表达式

-是一个左值(但不是位字段),以及“ cv1 T1 ”是参考兼容“ cv2 T2 ”,或

-有一个类型(即, T2是一个类型),其中, T1是不能引用相关于T2 ,并且可以隐式转换到类型的左值“ cv3 T3 ”,其中“ cv1 T1 ”是参考兼容“ cv3 T3 ” [...],

然后将参考结合到初始化表达式左值在第一种情况下,并在第二种情况下,转换的左值的结果(或者,在任一情况下,对对象的适当的基类的子对象)。 [...]

[...]

- 否则,应参考是一个左值参照非易失性const的类型(即,CV1应常数),或参考应一个rvalue参考 。 [ 实施例:

 double& rd2 = 2.0; // error: not an lvalue and reference not const int i = 2; double& rd3 = i; // error: type mismatch and reference not const 

末端示例 ]



Answer 2:

不,你不能绑定一个临时的非const左值参考。

T f();

T& t1 = f(); // won't compile
const T& t2 = f(); // OK
T&& t3 = f(); // OK

这是一项安全功能。 由左值是大约反正死变异暂时是最有可能的一个逻辑错误,所以它不是由语言允许的。

需要注意的是,由于RVO比做法:

T&& t3 = f();

T t3 = f();

是equivilent。



文章来源: Is it valid to bind non-const lvalue-references to rvalues in C++ 11?(modified)