繁体   English   中英

一个VS2010错误? 允许将非常量引用绑定到右值而没有警告?

[英]One VS2010 bug ? Allowing binding non-const reference to rvalue WITHOUT EVEN a warning?

string foo() { return "hello"; }
int main() 
{
    //below should be illegal for binding a non-const (lvalue) reference to a rvalue
    string& tem  = foo();   

    //below should be the correct one as only const reference can be bind to rvalue(most important const)
    const string& constTem = foo();   
}
  1. GCC是好的人给一个编译错误 :类型的非const引用无效初始化std::string&从临时类型std::string
  2. VS2008还不错,至少它给出了编译警告 :警告C4239:使用了非标准扩展名:'initializing':从std::string转换为std::string &非常量引用只能绑定到左值
  3. 这是有问题的一个-VS2010(SP1)可以很好地编译,没有任何错误或警告,为什么??! 我知道VS2010中的右值引用可用于与右值绑定,但是我没有使用&& ,而是在演示代码中,我只是在使用非常量左值引用!

somone可以在这里帮助我解释VS2010的行为吗? 这是一个错误! 谢谢

这是VS编译器的已知问题/功能。 他们一直允许这样做,并且似乎没有任何推动力去删除该扩展名

编译器将在启用“禁用语言扩展”的情况下发出错误,并在/ W4处发出警告。 但是,删除此代码将破坏以前的编译代码,Microsoft非常不愿意这样做。 这也是为什么他们不会修复SFINAE支持的原因。

几年后以及许多版本的Visual Studio之后,我们仍然遇到这种“扩展”,这会引起意外和头痛。 叹...

解决方法是将警告C4239变成错误。 这将防止MSVC编译试图将非const左值引用绑定到临时代码的代码,并给您带来清晰的编译器错误。 只需将/we4239添加到编译器定义或cl命令行参数中。

在Visual Studio中:“项目属性”>“ C / C ++”>“所有选项”>“将特定警告4239错误”>“添加4239 ,并确保用分号分隔任何其他数字。

在CMake中:

if(MSVC)
    add_definitions("/we4239")
endif()

这似乎比使用/Za 禁用所有语言扩展更好,后者正式不建议这样做。 在我的大型代码库中,添加/Za导致Microsoft自己的winnt.h标头超过1500个编译器错误。

此问题有一个更糟糕的变体:

class Foo {
  int _val;
public:
  Foo(int v) : _val(v) {}
  void F() { std::cout << _val << std::endl; }
};

class Bar {
  Foo& f;
public:
  Bar(Foo& f) : f(f) {}
  void F() { f.F(); }
};

int main() {
  Bar b(Foo(3));
  b.F();
}

所以:在调用bF() bf指向什么? 上面的示例是使用VS2013默认的Debug设置编译的,运行时没有崩溃并且不会显示3 ,但是我怀疑任何更复杂的示例都会导致堆栈损坏。 如果没有,并且编译器正在做一些“聪明”的事情来使其工作,那么我想它实际上正在做的是:

class Foo {
  int _val;
public:
  Foo(int v) : _val(v) {}
  void F() { std::cout << _val << std::endl; }
};

class Bar {
  Foo f;
public:
  Bar(Foo&& f) : f(f) {}
  void F() { f.F(); }
};

int main() {
  Bar b(Foo(3));
  b.F();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM