将非const左值引用绑定到C ++ 11中的rvalues是否有效?(已修改)

时间:2013-05-11 03:44:25

标签: c++ visual-studio-2012 c++11 lvalue rvalue

我知道在c ++ 03中,一个非const引用不能绑定到rvalues。

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是一个自定义类,我不明白为什么前两行编译。z引用的临时引用在main内部范围的末尾被破坏。标准是否对此有所说明?

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

我刚看到一个类似的问题:One VS2010 bug ? Allowing binding non-const reference to rvalue WITHOUT EVEN a warning?

2 个答案:

答案 0 :(得分:5)

  

应该在c ++ 11中工作吗?

不,不应该。

  

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

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

  

标准是否对此有所说明?

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

  

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

     

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

     
    

- 是左值(但不是位字段),“cv1 T1”与“cv2 T2”或

引用兼容          

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

  
     

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

     

[...]

     

- 否则,引用应是对非易失性const类型的左值引用(即,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
     

- 示例]

答案 1 :(得分:0)

不,你不能将临时绑定到非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();

是等同的。