6

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

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";
  }
};

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

4

2 回答 2

7

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

不,不应该。

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

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

标准对此有任何说明吗?

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

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

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

— 是一个左值(但不是位域),并且“<code>cv1 T1”与“<code>cv2 T2”是引用兼容的,或者

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

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

[...]

否则,引用应为对非易失性 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

—结束示例]

于 2013-05-11T08:46:34.547 回答
1

不,您不能将临时绑定到非常量左值引用。

T f();

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

这是一项安全功能。用一个无论如何都要死的左值来改变一个临时值很可能是一个逻辑错误,所以语言不允许这样做。

请注意,由于 RVO 比在实践中:

T&& t3 = f();

T t3 = f();

是等价的。

于 2013-05-11T05:27:57.143 回答