有人可以帮助我理解以下代码导致警告的原因
struct A
{
A() : _a( 0 ) {}
const int& _a;
};
int main()
{
A a;
}
带警告
warning: binding reference member '_a' to a temporary value [-Wdangling-field]
A() : _a( 0 ) {}
但是此代码(其中std::move
用于初始化成员_a
)不会:
struct A
{
A() : _a( std::move(0) ) {}
const int& _a;
};
int main()
{
A a;
}
Aren&t 0
和std::move( 0 )
两个r值?
答案 0 :(得分:9)
这是一个表达式:
0
这是一个非常小的表达,是的。但这是一种表达方式。
评估表达式后,它就会消失。它消失了。加入合唱团隐形。去见它的制造商。它变成了一个前表达。
确实,将const
引用绑定到临时值会将临时值的范围扩展到封闭范围的末尾。
但在这种情况下,表达式的范围是构造函数。构造函数完成后,临时值将被销毁。
您的编译器注意到,对表达式的const
引用仍然作为类成员继续存在。您的编译器建议您使用类成员现在将导致未定义的行为。你的编译器想成为你的朋友。您的编译器不希望您编写错误代码,因此您可以从编译器获得一些免费,友好的建议。
在另一种情况下,您添加了一些稍微复杂的附加代码。它仍然是未定义的行为,但代码现在足够复杂,编译器无法看到未定义的行为结果。但它仍然是同一个错误。
当编译器看到它们时,编译器会尝试警告您潜在的问题。不幸的是,编译器每次都找不到所有可能的潜在问题。但是,很明显,编译器会让你知道。
答案 1 :(得分:-1)
他们的回报值并不完全相同。 来自cppreference.com
特别是,std :: move会生成一个标识的 xvalue 表达式 它的论点t。它完全等同于static_cast到 rvalue 参考类型。
现在,看一下rvalue引用,我们看到第二个例子中的对象“0”可以活得更久:
在这种情况下,可以使用右值初始化右值参考 由rvalue标识的对象的生命周期延长到 参考范围结束。
此类引用(rvalue引用)随后被分配给类成员_a,这是允许的,因此您没有错误。
此外,对临时的rvalue引用可以在移动构造函数中使用,因此如果你正在初始化的成员有它,我没有看到问题。但是,在C ++中,您永远不会知道未定义的行为何时会突然袭击您:)