[英]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();
}
std::string&
从临时类型std::string
std::string
转换为std::string &
非常量引用只能绑定到左值 &&
,而是在演示代码中,我只是在使用非常量左值引用! 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.