使用lambda表达式的右值和左值引用-gcc与msvc 在C++中,将rValp隐式转换为LValk引用是非法的。 考虑下面的代码,其中一个LValk引用绑定到一个rValm(lambda):

使用lambda表达式的右值和左值引用-gcc与msvc 在C++中,将rValp隐式转换为LValk引用是非法的。 考虑下面的代码,其中一个LValk引用绑定到一个rValm(lambda):,c++,visual-c++,gcc,c++11,C++,Visual C++,Gcc,C++11,gcc(4.8.1)不接受此类代码(完全有道理)。 但是,微软编译器接受它意味着它接受非标准代码,或者C++允许特定的情况下,LValk引用绑定到一个RUBLATDA表达式。 问题是:哪个假设是正确的 但是,微软编译器接受它意味着它接受非标准代码,或者C++允许特定的情况,其中一个LValk引用绑定到一个RUBEDLAMDA表达式。 MSVC以拥有这个(不是很好的)编译器扩展而闻名。它只允许将右值绑定到非常量的左值引用: A& x = A(); // Illegal in C++, al

gcc(4.8.1)不接受此类代码(完全有道理)。 但是,微软编译器接受它意味着它接受非标准代码,或者C++允许特定的情况下,LValk引用绑定到一个RUBLATDA表达式。 问题是:哪个假设是正确的

<>但是,微软编译器接受它意味着它接受非标准代码,或者C++允许特定的情况,其中一个LValk引用绑定到一个RUBEDLAMDA表达式。 MSVC以拥有这个(不是很好的)编译器扩展而闻名。它只允许将右值绑定到非常量的左值引用:

A& x = A(); // Illegal in C++, allowed by MSVC

您问题的核心是:右值是否可以绑定到非常量左值引用

标准上说
。右值只能绑定到常量左值引用

我认为相关的标准段落是8.5.3/5

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

  • 否则,该引用应为非易失性常数类型的左值引用(即cv1应为常数),或该引用 应为右值参考
但是微软有一个长期的“特征”,允许这个“强>非标准<强/强行为”来解释你所看到的。

< > >萨特(ISO C++标准委员会主席):

一个符合条件的C++编译器总是允许非法的C++代码编译并赋予它一些意义。嘿,如果一些古怪的编译器编写者愿意实现这个扩展,可能会允许允许内嵌的COBOL,也许是经过了太多龙舌兰。对于某些扩展,C++标准要求编译器至少发出一些诊断,说代码不是有效的ISO C++,就像编译器一样。 他进一步解释了以下示例是如何非法的:

// Example 2

string f() { return "abc"; }

void g() {
string& s = f();       // illegal?
  cout << s << endl;
}
//示例2
字符串f(){返回“abc”;}
void g(){
string&s=f();//非法吗?

该特性对函数参数有意义吗:
void f(A&A){…}
可以用
…f(A()调用).
它有它的用例。@MartinBa:我真的不喜欢这个扩展。首先是因为这是相对于标准而言的一个重大行为变化,其次是因为它对您的影响比它对您的帮助更大。@Martin Ba:如果您首先在MS上开发,然后在其他平台上测试,这会使多平台开发变得更加复杂平台…有时你会使用右值作为非常量左值引用,MSVC不会告诉你。所以它在GCC上出现得晚了一点…总是很烦人。至少在MSVC中关闭它的编译器开关是件好事!!是的,这是一个功能。有时很有用。我们有什么问题/答案可以解释这一点吗?@Martin巴:在回答你的评论时,除了标准之外,任何东西都不是一个特性,而是一个bug。C++不是完美的,但是厂商特有的“改进”是一个PITA,当涉及到互操作性时,它们应该被火杀死。YMMV(但是当你开始跨平台项目时,这变得非常重要)。@syam:许多特定于供应商的扩展是必不可少的。没有特定于操作系统的API,任何人都不会有任何进展。如果在MSVC中启用警告级别4,就会收到关于使用非标准扩展的警告。鉴于此,我看不出为那些在单一平台上编写的人提供一些方便的语言扩展有什么害处。@Mikewolf:W嗯,我对MSVC不太了解,因为我已经很久没有使用它了,但我知道GCC:任何非标准扩展都要求你明确选择加入或面临警告。在我看来,这比MSVC要求你选择退出要明智得多。同样,YMMV。
// Example 2

string f() { return "abc"; }

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