r 值在不使用 std::move 的情况下导致警告
r-value causes a warning without the use of std::move
谁能帮我理解为什么下面的代码会导致警告
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;
}
0
和 std::move( 0 )
不是 r 值吗?
这是一个表达式:
0
这是一个非常小的表达,是的。但它是一个表达式。
一旦表达式被求值,它就会消失。它消失了。加入无形的合唱团。去见它的制造者。它变成了一个ex表达式。
确实,将 const
引用绑定到临时值会扩展临时值的范围,直到封闭范围结束。
但在这种情况下,表达式的范围是构造函数。构造函数完成后,临时值将被销毁。
您的编译器注意到一个事实,即对表达式的 const
引用仍然作为 class 成员继续存在。您的编译器建议您使用 class 成员现在将导致未定义的行为。你的编译器想成为你的朋友。您的编译器不希望您编写有缺陷的代码,因此您将从编译器那里获得一些免费、友好的建议。
在另一种情况下,您添加了一些稍微复杂一些的附加代码。它仍然是未定义的行为,但代码现在已经足够复杂,编译器无法看到未定义的行为结果。但是还是一样的bug。
当编译器发现潜在问题时,编译器会尝试警告您。不幸的是,编译器无法每次都找到所有可能的潜在问题。但是,当它很明显时,编译器会让您知道。
它们的return值并不完全相同。
来自 cppreference.com
In particular, std::move produces an xvalue expression that identifies
its argument t. It is exactly equivalent to a static_cast to an rvalue
reference type.
现在,查看右值引用,我们看到第二个示例中的对象“0”可以活得更久:
An rvalue may be used to initialize an rvalue reference, in which case
the lifetime of the object identified by the rvalue is extended until
the scope of the reference ends.
这样的引用(右值引用)随后分配给 class 成员 _a,这是允许的,所以你没有错误。
此外,可以在移动构造函数中使用对临时对象的右值引用,因此如果您正在初始化的成员有它,我看不出问题所在。然而,在 C++ 中,你永远不知道什么时候未定义的行为会突然袭击你:)
谁能帮我理解为什么下面的代码会导致警告
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;
}
0
和 std::move( 0 )
不是 r 值吗?
这是一个表达式:
0
这是一个非常小的表达,是的。但它是一个表达式。
一旦表达式被求值,它就会消失。它消失了。加入无形的合唱团。去见它的制造者。它变成了一个ex表达式。
确实,将 const
引用绑定到临时值会扩展临时值的范围,直到封闭范围结束。
但在这种情况下,表达式的范围是构造函数。构造函数完成后,临时值将被销毁。
您的编译器注意到一个事实,即对表达式的 const
引用仍然作为 class 成员继续存在。您的编译器建议您使用 class 成员现在将导致未定义的行为。你的编译器想成为你的朋友。您的编译器不希望您编写有缺陷的代码,因此您将从编译器那里获得一些免费、友好的建议。
在另一种情况下,您添加了一些稍微复杂一些的附加代码。它仍然是未定义的行为,但代码现在已经足够复杂,编译器无法看到未定义的行为结果。但是还是一样的bug。
当编译器发现潜在问题时,编译器会尝试警告您。不幸的是,编译器无法每次都找到所有可能的潜在问题。但是,当它很明显时,编译器会让您知道。
它们的return值并不完全相同。 来自 cppreference.com
In particular, std::move produces an xvalue expression that identifies its argument t. It is exactly equivalent to a static_cast to an rvalue reference type.
现在,查看右值引用,我们看到第二个示例中的对象“0”可以活得更久:
An rvalue may be used to initialize an rvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.
这样的引用(右值引用)随后分配给 class 成员 _a,这是允许的,所以你没有错误。
此外,可以在移动构造函数中使用对临时对象的右值引用,因此如果您正在初始化的成员有它,我看不出问题所在。然而,在 C++ 中,你永远不知道什么时候未定义的行为会突然袭击你:)