为什么在我的代码中调用复制构造函数而不是移动构造函数?
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;
}
您对类型和值类别感到困惑。
(强调我的(
每个C++表达式(运算符及其操作数、文本、变量名称等(都具有两个独立的属性:类型和值类别。
作为命名变量,a
是一个左值。
以下表达式是左值表达式:
- 变量的名称,...
- 。
然后,对于A b = a;
,选择复制构造函数。正如您尝试的那样,static_cast<decltype(a)>(a);
会将其转换为 xvalue(即右值(;您也可以使用std::move
.
A b = std::move(a);
以下表达式是xvalue 表达式:
- 函数调用或重载运算符表达式,其返回类型是对对象的 rvalue 引用,例如
std::move(x)
;- 。
A&& a = A();
不给你一个右值。将任何值视为右值的一种方法是您无法获取它的地址。如果你能得到它的地址,那么它很可能是一个左值。 所以,在你的情况下
auto address_of_a = &a;
是可能的(所以,a 是左值(。
decltype(a)
是 A&&(右值类型(。 所以类型转换为 A&& 会给你右值
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;
如果定义复制分配,将成功。
默认构造/复制构造/移动或复制赋值将起作用,只要所有元素都是简单的复制/可移动的。
相关文章:
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么调用复制构造函数而不是移动构造函数?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 具有已删除移动和复制构造函数的类的就地构造
- 移动构造函数和右值引用
- 使用移动调用对等构造函数unique_ptr默认构造函数
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 具有专用化的模板类中的可靠条件复制和移动构造函数
- 构造函数采用std::string_view与std::string并移动
- C++:为什么不调用移动构造函数?
- 了解构造函数在移动、复制、赋值语义中的行为
- 没有移动的构造函数移动课程
- 引用绑定和复制构造函数/移动构造函数
- 构造函数移动
- C++ 向量实现 - 移动构造函数 - 移动与前进
- 我真的必须取消移动构造函数/移动结构中的所有成员还是只是指针
- 将类(没有默认构造函数)移动到另一个类的move构造函数中