关于C++ 的默认函数
默认构造函数,拷贝构造,赋值拷贝,移动拷贝,移动赋值拷贝,默认析构函数。移动拷贝函数和移动赋值拷贝是后面新加的,移动构造函数使右值对象拥有的资源无需赋值即可移动到左值中。
目前的经验来看,这三者主要是应对深拷贝,浅拷贝的问题。这类场景通常是对象持有一个数据指针。
浅拷贝,直接赋值数据指针,那就有两个指针指向同一份数据,这个就引入了很多风险,比如重复释放导致Crash 的问题。
深拷贝,为了解决两个不同的对象持有同一份数据,深拷贝直接把数据复制一份,这样两个对象的数据就没有关联了。但是这样做的缺点就是资源消耗大,比如cv::Mat 的 clone操作。
移动操作,就是把数据直接 move到目标对象,就像剪切粘贴一样,把自己的数据赋值给目标对象,然后把自己的指针置为空。这样就避免了两个对象指向同一份数据的情况。但是这也将导致源数据失效,所有移动也是有代价的,具体取决于场景,比如一些临时对象,就可以用移动操作来转移自己的数据。
具体解释可以看这里: https://learn.microsoft.com/zh-cn/cpp/cpp/move-constructors-and-move-assignment-operators-cpp?view=msvc-170
大概长这个样子:
#include <iostream>
#include <algorithm>
#include <vector>
class MemoryBlock
{
public:
// Simple constructor that initializes the resource.
explicit MemoryBlock(size_t length)
: _length(length)
, _data(new int[length])
{
std::cout << "In memory block constructor, length = "
<< _length << "." << std::endl;
}
// Destructor.
~MemoryBlock()
{
std::cout << "In memory block destructor, length = "
<< _length << ".";
if (_data != nullptr)
{
std::cout << " Deleting resource.";
// Delete the resource.
delete[] _data;
}
std::cout << std::endl;
}
// Copy constructor.
MemoryBlock(const MemoryBlock& othre)
: _length(othre._length)
, _data(new int[othre._length])
{
std::cout << "In memory block copy constructor, length = "
<< othre._length << ". Copying resource." << std::endl;
std::copy(othre._data, othre._data + _length, _data);
}
// Copy assignment operator.
MemoryBlock& operator=(const MemoryBlock& other)
{
std::cout << "In memory block copy assignment operator, length = "
<< other._length << ". Copying resource." << std::endl;
if (this != &other)
{
// Free the existing resource.
delete[] _data;
_length = other._length;
_data = new int[_length];
std::copy(other._data, other._data + _length, _data);
}
return *this;
}
// Move copy constructor.
MemoryBlock(MemoryBlock&& other)
: _data(nullptr)
, _length(0)
{
std::cout << "In memory block move constructor, length = "
<< other._length << ". Moving resource." << std::endl;
_data = other._data;
_length = other._length;
other._data = nullptr;
other._length = 0;
}
// Move assignment operator.
MemoryBlock& operator=(MemoryBlock&& other)
{
std::cout << "In memory block move assignment operator, length = "
<< other._length << ". Moving resource." << std::endl;
if (this != &other)
{
delete[] _data;
_data = other._data;
_length = other._length;
other._data = nullptr;
other._length = 0;
}
return *this;
}
// Retrieves the length of the data resource.
size_t Length() const {
return _length;
}
private:
size_t _length; // The length of the resource.
int* _data; // The resource.
};
int