复制构造函数替换移动构造函数
Copy constructor replace Move constructor?
我从链接学习移动语义
我有一个类
class Holder
{
public:
Holder(int size) // Constructor
{
m_data = new int[size];
m_size = size;
}
~Holder() // Destructor
{
delete[] m_data;
}
Holder(const Holder& other)
{
cout << "copy constructor" << endl;
m_data = new int[other.m_size];
memcpy(m_data, other.m_data, sizeof(int));
m_size = other.m_size;
}
Holder &operator=(const Holder& other)
{
if (this == &other)
return *this;
delete[]m_data;
m_data = new int[other.m_size];
memcpy(m_data, other.m_data, sizeof(int));
m_size = other.m_size;
return *this;
}
private:
int* m_data;
size_t m_size;
};
此类具有复制构造函数,例如:
Holder(const Holder& other)
{
cout << "copy constructor" << endl;
m_data = new int[other.m_size];
memcpy(m_data, other.m_data, sizeof(int));
m_size = other.m_size;
}
然后移动构造函数已实现:
Holder(Holder&& other) // <-- rvalue reference in input
{
m_data = other.m_data; // (1)
m_size = other.m_size;
other.m_data = nullptr; // (2)
other.m_size = 0;
}
我有一个问题:为什么我们不以下内容实现复制构造函数:
Holder( Holder& other)
{
m_data = other.m_data;
m_size = other.m_size;
other.m_data = nullptr;
other.m_size = 0;
}
您能告诉我为什么这种方式不使用吗?谢谢
您对该"复制构造函数"的实现在语义上是副本构造函数和移动构造函数之间的某些内容,这将令人困惑,然后危险。如果您的意图是始终移动并且永远无法复制对象,那么您可以强迫该类对此不可复制:
Holder(const Holder& other) = delete;
Holder& operator=( const Holder& ) = delete;
即使您遵循默认复制构造函数和默认分配的编译器的非生成规则,明确删除这些方法也更加清楚。
我猜出于安全原因。尽管您所描述的内容是可以的(并且在知道一个人在做什么时正确(,但是这样做可能最终会带有一个看起来很满但实际上是空的对象。
在一般移动中,构造函数对于使用以下临时值的使用更有用:
Holder a_function(...){...}
然后可用于构造:
Holder object(a_function(...));
或在执行以下操作时避免重新分配/复制大量数据/内存:
Holder object(Holder(100));
,但特别是对于没有默认构造函数的这种情况(一般而言,每个对象都应该在构造后满足(,通过将复制构造函数作为您的建议(类似于移动构造函数(,然后通过:
Holder object1(100);
Holder object2(object1);
一个人最终会以object1
的形式看起来像普通对象,但它是空的。因此,它可能会成为bug/s后来的来源。
尽管很明显,但我应该补充一点,毁坏对象没有问题。只是,如果没有某种类型的安全守卫(边界检查(,则不知道它的空虚,很可能会导致非法内存访问。
我有一个问题:为什么我们不以下内容实现复制构造函数 :
Holder( Holder& other) { m_data = other.m_data; m_size = other.m_size; other.m_data = nullptr; other.m_size = 0; }
您能告诉我为什么这种方式不使用吗?
上面的代码不是从其他代码复制状态,而是将其他资源转移到创建的当前对象。
。来自移动构造函数
移动构造函数通常"窃取"该论点持有的资源 (例如,指向动态分配的对象,文件描述符,TCP 插座,I/O流,运行线程等(而不是制作副本 他们,并将论点留在某些有效但其他方面 不确定状态。
Holder A;
Holder B(std::move(A));
// B is created by calling move constructor
// Resources held by A are transferred to B (ref1)
Holder C;
Holder D(C);
//C is created by calling copy constructor
//state or resources of C, D are same and C can be used after this
//Object C usable
ref1
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么调用复制构造函数而不是移动构造函数?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 具有已删除移动和复制构造函数的类的就地构造
- 移动构造函数和右值引用
- 使用移动调用对等构造函数unique_ptr默认构造函数
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 具有专用化的模板类中的可靠条件复制和移动构造函数
- 构造函数采用std::string_view与std::string并移动
- C++:为什么不调用移动构造函数?
- 了解构造函数在移动、复制、赋值语义中的行为
- 没有移动的构造函数移动课程
- 引用绑定和复制构造函数/移动构造函数
- 构造函数移动
- C++ 向量实现 - 移动构造函数 - 移动与前进
- 我真的必须取消移动构造函数/移动结构中的所有成员还是只是指针
- 将类(没有默认构造函数)移动到另一个类的move构造函数中