2

考虑以下示例:

#include <iostream>
#include <string>

struct foo { std::string value; };
inline foo bar() { return { "42" }; }

std::string my_func() {
    auto &x = bar();
    ^^^^^^^^^^^^^^^^
    return x.value;
}

int main() {
  std::cout << my_func() << std::endl;  
}

编译GCCCLANG会发出相同的错误,很可能是正确的:

错误:从“foo”类型的右值初始化“foo&”类型的非常量引用无效

然而,令我惊讶的是,它在 VC++2015 中编译并运行良好。

  • 这是VC++2015的bug吗?
  • 当语句呈现程序格式错误时,标准是否规定auto可以隐式添加const对象?
4

3 回答 3

3

这是VC++2015的bug吗?

该标准允许实现接受格式错误的代码作为扩展。然而,仍然需要实现来发出诊断(这可能只是意味着“当某些标志打开时发出警告”)。

当语句使程序格式错误时,标准是否规定auto可以向对象隐式添加常量?

不,标准要求auto推导使用与模板参数推导相同的规则(初始化列表除外)。如果T&不接受,auto&就不会。

于 2015-11-05T22:18:13.637 回答
2

不,auto不能添加常量。但是,MSVC++ 一直有一个扩展,即非常量左值引用可以绑定到右值。

/Za我认为,您可以使用开关禁用此扩展程序。

于 2015-11-05T22:17:39.393 回答
1

这是VC++2015的bug吗?

雷德蒙德的被告通常称其为“功能”,但它是编译器混乱中的一个完全愚蠢的错误(可使用 修复/Za)。让我们看看为什么...

auto &x = bar();

好的,所以你在打电话bar(),不是吗?这会产生一个rvalue,即没有地址的对象。现在,您不能将lvalue(可以获取其地址的对象)引用(又名:)绑定&rvalue. 到目前为止,这就是您的代码非法的原因。

但是,C++ 语言中有一条特殊规则允许const lvalue引用绑定到rvalue,从而有效地延长了它的生命周期。所以,这将是有效的代码......

const auto &x = foo();

编辑:顺便说一句...

当语句呈现程序格式错误时,标准是否规定 auto 可以向对象隐式添加常量?

用非标准术语/简单的英语来说,如果T&被拒绝,那么auto&. CV 限定符 (constvolatile)不会自动从auto.

我希望这对你有所启发!

于 2015-11-05T22:23:39.477 回答