我知道在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引用到右值,甚至没有一个警告?
应在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
末端示例 ]
不,你不能绑定一个临时的非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)