为什么在我的代码中调用复制构造函数而不是移动构造函数?
Why copy constructor is called instead of move constructor in my code?
我正在尝试了解移动构造函数和右值引用。
所以我在 https://www.onlinegdb.com/online_c++_compiler 上尝试了这段代码。
但是结果让我很困惑。
#include <iostream>
#include <type_traits>
class A {
public:
A() { std::cout << "Constructed" << std::endl; }
A(const A& )= delete;
A(A&&) { std::cout << "Move Constructed" << std::endl; }
};
int
main ()
{
A&& a = A();
A b = a; // error: use of deleted function ‘A::A(const A&)’
//A b = static_cast<decltype(a)>(a); // This works, WTF?
std::cout << std::is_rvalue_reference<decltype(a)>::value << std::endl; // pretty sure a is rvalue reference.
return 0;
}
您混淆了 类型 和 value categories。
(强调我的)
Each C++ expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties: a type and a value category.
作为命名变量,a
是一个左值。
The following expressions are lvalue expressions:
- the name of a variable, ...
- ...
然后 A b = a;
选择复制构造函数。正如您所尝试的那样,static_cast<decltype(a)>(a);
会将其转换为 xvalue(右值);你也可以使用 std::move
.
A b = std::move(a);
The following expressions are xvalue expressions:
- a function call or an overloaded operator expression, whose return type is rvalue reference to object, such as
std::move(x)
;
- ...
A&& a = A();
不给你右值。将任何值视为右值的一种方法是您无法获取它的地址。如果你能得到它的地址,那么它很可能是一个左值。
所以,在你的情况下
auto address_of_a = &a;
是可能的(所以,a 是左值)。
decltype(a)
是A&&(右值类型)。所以类型转换为 A&& 会给你 rvalue
A b = a;
失败是因为 a 是左值,所以它正在寻找 A(const A&)。
A b = std::move(a); // or
A b = A{}; // rvalue
会成功,因为现在它会寻找 A(A&&)
A b;
A c = A{};
b = std::move(c);
如果您在
期间将您的移动分配定义为已删除,将会失败
b = c;
如果您定义复制分配,将会成功。
默认 construct/copy construct/move 或复制赋值只要所有元素都是平凡的 copy/movable.
就可以工作
我正在尝试了解移动构造函数和右值引用。 所以我在 https://www.onlinegdb.com/online_c++_compiler 上尝试了这段代码。 但是结果让我很困惑。
#include <iostream>
#include <type_traits>
class A {
public:
A() { std::cout << "Constructed" << std::endl; }
A(const A& )= delete;
A(A&&) { std::cout << "Move Constructed" << std::endl; }
};
int
main ()
{
A&& a = A();
A b = a; // error: use of deleted function ‘A::A(const A&)’
//A b = static_cast<decltype(a)>(a); // This works, WTF?
std::cout << std::is_rvalue_reference<decltype(a)>::value << std::endl; // pretty sure a is rvalue reference.
return 0;
}
您混淆了 类型 和 value categories。
(强调我的)
Each C++ expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties: a type and a value category.
作为命名变量,a
是一个左值。
The following expressions are lvalue expressions:
- the name of a variable, ...
- ...
然后 A b = a;
选择复制构造函数。正如您所尝试的那样,static_cast<decltype(a)>(a);
会将其转换为 xvalue(右值);你也可以使用 std::move
.
A b = std::move(a);
The following expressions are xvalue expressions:
- a function call or an overloaded operator expression, whose return type is rvalue reference to object, such as
std::move(x)
;- ...
A&& a = A();
不给你右值。将任何值视为右值的一种方法是您无法获取它的地址。如果你能得到它的地址,那么它很可能是一个左值。 所以,在你的情况下
auto address_of_a = &a;
是可能的(所以,a 是左值)。
decltype(a)
是A&&(右值类型)。所以类型转换为 A&& 会给你 rvalue
A b = a;
失败是因为 a 是左值,所以它正在寻找 A(const A&)。
A b = std::move(a); // or
A b = A{}; // rvalue
会成功,因为现在它会寻找 A(A&&)
A b;
A c = A{};
b = std::move(c);
如果您在
期间将您的移动分配定义为已删除,将会失败b = c;
如果您定义复制分配,将会成功。
默认 construct/copy construct/move 或复制赋值只要所有元素都是平凡的 copy/movable.
就可以工作