【问题标题】:rvalue to lvalue conversion Visual Studio右值到左值转换 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 临时成员函数。然而,使用“直接”语法附加非常量引用是非法的。如我的回答所示,前者实际上允许人们解决后者。

标签: c++ visual-studio


【解决方案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 编译器允许这样做。警告告诉您代码由于扩展而正在编译,并且不会与任何其他编译器一起编译。

【讨论】:

    猜你喜欢
    • 2017-11-24
    • 1970-01-01
    • 2013-07-12
    • 2014-01-17
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    相关资源
    最近更新 更多