右值到左值转换 Visual Studio

Posted

技术标签:

【中文标题】右值到左值转换 Visual Studio【英文标题】:rvalue to lvalue conversion Visual Studio 【发布时间】:2012-07-16 16:33:48 【问题描述】:

在 Visual Studio 2012RC 中有一些非标准扩展。例如这段代码编译:

#include <string>

using namespace std;

void value(string& value)

    value = "some";


int main()

    value(string("nice"));

并收到警告说它是非标准扩展。所以,我想了解它是如何真实的以及代码如何转换(右值引用或带有 const_cast 的 const 引用)?

【问题讨论】:

AFAIK,Visual Studio 2010(可能还有 2008)也支持这种行为。 VC++ 编译器允许修改临时对象。 请注意,这是最糟糕的风格,最坏的情况是容易出错 ("Don't you care it's a temporary you are modifying?") @flamingo:嗯,在 C++ 中修改临时对象从来都不是违法的。在 C++ 中,一直允许调用非 const modifying 临时成员函数。然而,使用“直接”语法附加非常量引用是非法的。如我的回答所示,前者实际上允许人们解决后者。 【参考方案1】:

类类型的临时对象仍然是对象。它存在于内存中的某个地方,这意味着编译器能够附加对它的引用并没有什么不寻常的。在物理层面上,它是常量引用还是非常量引用都没有区别。换句话说,在这种情况下,语言限制纯粹是概念性的、人为的。编译器只是忽略了这个限制。这里没有必要“转换”任何东西。引用只是直接附加到对象上,无论该对象恰好位于何处。

基本上,对于提供外部单词访问其this 指针值(或左值访问*this)的类,可以立即轻松地模拟行为

struct S 
  S& get_lvalue()  return *this; 
;

void foo(S& s);
...

foo(S().get_lvalue());

上面的代码是完全合法的,它可以绕过上述限制。您可以认为 MSVC++ 行为与此等价。

【讨论】:

谢谢。有趣的。接受。 如果我们在函数之外存储临时文件,这会导致 UB 吗? @Guillaume07:你能改写一下吗?我不明白您所说的“库存”是什么意思。 @Andrey:对不起,我的意思是库存:如果你在函数之外保留临时的引用 大概 MSVC 扩展也延长了临时的生命周期【参考方案2】:

基本上,VS 会在某处分配空间并让引用指向它,好像它是一个没有 const 性的const 的引用(或者在 C++11 中右值引用)。

您可以使用/Za(禁用语言扩展)编译器开关来禁用此行为

属性 -> C/C++ -> 语言

如果我没记错的话。

【讨论】:

谢谢。好答案。已接受,但启用 /ZA 很糟糕,因为任何正确的代码都无法编译(在 C++11 下)。【参考方案3】:

在标准 C++ 中,您不能将临时 (rvalue / string("nice")) 绑定到非常量引用 (lvalue),但 microsoft 编译器允许这样做。警告告诉您代码由于扩展而正在编译,并且不会与任何其他编译器一起编译。

【讨论】:

以上是关于右值到左值转换 Visual Studio的主要内容,如果未能解决你的问题,请参考以下文章

无序映射的左值到右值转换

C++ 传递向量(左值到右值)

c++的左值(lvalue),右值(rvalue),移动语义(move),完美转发(forward)

将右值引用绑定到(自动生成的)左值

[c++11]右值引用移动语义和完美转发

[转][c++11]我理解的右值引用移动语义和完美转发