r值在不使用std :: move的情况下引发警告

时间:2016-11-18 13:24:17

标签: c++ c++14 move-semantics rvalue-reference

有人可以帮助我理解以下代码导致警告的原因

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 0std::move( 0 )两个r值?

2 个答案:

答案 0 :(得分:9)

这是一个表达式:

0

这是一个非常小的表达,是的。但这是一种表达方式。

评估表达式后,它就会消失。它消失了。加入合唱团隐形。去见它的制造商。它变成了一个前表达。

确实,将const引用绑定到临时值会将临时值的范围扩展到封闭范围的末尾。

但在这种情况下,表达式的范围是构造函数。构造函数完成后,临时值将被销毁。

您的编译器注意到,对表达式的const引用仍然作为类成员继续存在。您的编译器建议您使用类成员现在将导致未定义的行为。你的编译器想成为你的朋友。您的编译器不希望您编写错误代码,因此您可以从编译器获得一些免费,友好的建议。

在另一种情况下,您添加了一些稍微复杂的附加代码。它仍然是未定义的行为,但代码现在足够复杂,编译器无法看到未定义的行为结果。但它仍然是同一个错误。

当编译器看到它们时,编译器会尝试警告您潜在的问题。不幸的是,编译器每次都找不到所有可能的潜在问题。但是,很明显,编译器会让你知道。

答案 1 :(得分:-1)

他们的回报值并不完全相同。 来自cppreference.com

  

特别是,std :: move会生成一个标识的 xvalue 表达式   它的论点t。它完全等同于static_cast到 rvalue   参考类型。

现在,看一下rvalue引用,我们看到第二个例子中的对象“0”可以活得更久:

  

在这种情况下,可以使用右值初始化右值参考   由rvalue标识的对象的生命周期延长到   参考范围结束。

此类引用(rvalue引用)随后被分配给类成员_a,这是允许的,因此您没有错误。

此外,对临时的rvalue引用可以在移动构造函数中使用,因此如果你正在初始化的成员有它,我没有看到问题。但是,在C ++中,您永远不会知道未定义的行为何时会突然袭击您:)