在 C++ 11 中将非常量左值引用绑定到右值是否有效?(修改)

2021-12-27 00:00:00 c++ c++11 visual-studio-2012 rvalue lvalue

我知道在 c++03 中,非常量引用不能绑定到右值.

I know in c++03, an an non-const reference cannot be bound to rvalues.

T&t = getT(); 无效,在 C++11 中,我们可以这样做:T&&t = getT(); 但是上面的代码怎么样,在 c++11 中能用吗?

T& t = getT(); is invalid, and in c++11, we can do this: T&& t = getT(); but what about the above code, should that work in c++11?

我用 vs11 测试了下面的代码:

I tested the codes below with 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 是自定义类,不明白为什么前两行编译.z 引用的临时对象在内部作用域的末尾销毁主要的.标准对此有任何说明吗?

Foo is a custom class, I don't understand why the first two line compiles.The temporary referenced by z is destructed at the end of the inner scope of main. Does the standard say anything about this?

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

我刚看到一个类似的问题:一个 VS2010 错误?允许在没有警告的情况下绑定非常量引用到右值?

I just saw a similar question: One VS2010 bug ? Allowing binding non-const reference to rvalue WITHOUT EVEN a warning?

推荐答案

这应该在 C++11 中工作吗?

should that work in c++11?

不,不应该.

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

Foo is a custom class, I don't understand why the first two line compiles

它只能用 MSVC 编译.MSVC 有一个(可以说是有用的)编译器扩展,它允许将用户定义类型的左值绑定到右值,但标准本身禁止这样做.例如,请参阅这个现场示例,其中 GCC 4.7.2 拒绝编译您的代码.

It compiles only with MSVC. MSVC has an (arguably useful) compiler extension that allows binding lvalues of user-defined types to rvalues, but the Standard itself forbids this. See, for instance, this live example where GCC 4.7.2 refuses to compile your code.

标准对此有任何说明吗?

Does the standard say anything about this?

确实如此.根据 C++11 标准的第 8.5.3/5 段:

Indeed it does. Per paragraph 8.5.3/5 of the C++11 Standard:

对类型cv1 T1"的引用由cv2 T2"类型的表达式初始化,如下所示:

A reference to type "cv1 T1" is initialized by an expression of type "cv2 T2" as follows:

――如果引用是左值引用和初始化表达式

― If the reference is an lvalue reference and the initializer expression

― 是左值(但不是位域),并且cv1 T1"与cv2 T2"引用兼容,或

― is an lvalue (but is not a bit-field), and "cv1 T1" is reference-compatible with "cv2 T2," or

――有一个类类型(即T2是一个类类型),其中T1T2没有引用相关,并且可隐式转换为cv3 T3"类型的左值,其中cv1 T1"与cv3"引用兼容T3" [...],

― has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be implicitly converted to an lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible with "cv3 T3" [...],

然后引用绑定到第一种情况下的初始化表达式左值和左值结果在第二种情况下的转换(或者,在任何一种情况下,转换为适当的基类子对象物体).[...]

then the reference is bound to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object). [...]

[...]

――否则,引用应是对非易失性常量类型的左值引用(即,cv1 应为const),或者引用应该是一个右值引用.[ 示例:

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

――结束示例 ]

相关文章