6

在 C++ 中,将右值隐式转换为左值引用是非法的。考虑以下代码,其中左值引用绑定到右值(lambda):

int main()
{
    auto& f = []() -> void {};
    return 0;
}

gcc (4.8.1) 不接受这样的代码(非常有意义)。但是,Microsoft 编译器确实接受它,这意味着它要么接受非标准代码,要么 C++ 允许将左值引用绑定到右值 lambda 表达式的特殊情况。

问题:哪个假设是正确的?

4

3 回答 3

7

The core of your question is: can rvalues be bound to non-const lvalue references?

The Standard says no. rvalues can only be bound to const lvalue references.

I believe the relevant Standard paragraph is 8.5.3/5:

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

...

  • Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference.

However Microsoft has a long-standing "feature" that allows this non-standard behaviour, which explains what you're witnessing.

于 2013-06-15T20:38:40.633 回答
3

引用Herb Sutter(ISO C++ 标准委员会主席)的话:

一个符合标准的 C++ 编译器总是可以允许非法的 C++ 代码编译并赋予它一些意义——嘿,如果一些古怪的编译器编写者愿意实现那个扩展,它可以选择允许内联 COBOL,也许是在喝了太多龙舌兰酒之后。对于某些类型的扩展,C++ 标准要求编译器至少发出一些诊断信息,说明代码不是有效的 ISO C++,就像这个编译器一样。

他进一步解释了以下示例如何非法:

// Example 2

string f() { return "abc"; }

void g() {
string& s = f();       // illegal?
  cout << s << endl;
}

请访问 Sutter 的此链接以获得解释,以避免重复有关 SO 的文章。

于 2013-06-15T20:57:08.123 回答
3

但是,Microsoft 编译器确实接受它,这意味着它要么接受非标准代码,要么 C++ 允许将左值引用绑定到右值 lambda 表达式的特殊情况。

MSVC 以拥有这个(不是很好)编译器扩展而闻名。它只是允许将右值绑定到对非的左值引用const

A& x = A(); // Illegal in C++, allowed by MSVC
于 2013-06-15T20:37:09.497 回答