如何将动态分配的数据从对象移动到另一个对象?

Ign*_*ant 1 c++ memory temporary move-semantics c++11

我有一个用RAII编写的Array类(为了这个例子的目的,超简化):

struct Array
{
    Array(int size) {
        m_size = size;
        m_data = new int[m_size];
    }

    ~Array() {
        delete[] m_data;
    }

    int* m_data = nullptr;
    int  m_size = 0;
};
Run Code Online (Sandbox Code Playgroud)

然后我有一个函数,它接受一个数组的引用并对它进行一些操作.我使用临时数组temp来执行处理,因为有几个原因我不能直接使用引用.完成后,我想将数据从临时数据传输到真实数据:

void function(Array& array)
{
    Array temp(array.m_size * 2);

    // do heavy processing on `temp`...

    array.m_size = temp.m_size;
    array.m_data = temp.m_data;
}
Run Code Online (Sandbox Code Playgroud)

显而易见的问题是temp在函数末尾超出范围:它的析构函数被触发,而后者又删除了内存.这种方式array将包含不存在的数据.

那么将数据所有权从一个对象"移动"到另一个对象的最佳方法是什么?

ein*_*ica 6

你想要的是为你的数组类移动构造或移动赋值,这可以节省多余的副本.此外,它将帮助您使用std::unique_ptr哪个将为您分配内存的移动语义,因此您不需要自己直接进行任何内存分配.您仍然需要拉起袖子并遵循"零/三/五规则",在我们的例子中是五的规则(复制和移动构造函数,复制和移动赋值运算符,析构函数).

所以,试试:

class Array {
public:
    Array(size_t size) : m_size(size) {
        m_data = std::make_unique<int[]>(size);
    }

    Array(const Array& other) : Array(other.size) {
        std::copy_n(other.m_data.get(), other.m_size, m_data.get());
    }

    Array(Array&& other) : m_data(nullptr) {
        *this = other;
    } 

    Array& operator=(Array&& other) {
        std::swap(m_data, other.m_data);
        m_size = other.m_size;
        return *this;
    }

    Array& operator=(const Array& other) {
        m_data = std::make_unique<int[]>(other.m_size);
        std::copy_n(other.m_data.get(), other.m_size, m_data.get());
        return *this;
    }

    ~Array() = default;

    std::unique_ptr<int[]>  m_data;
    size_t                  m_size;
};
Run Code Online (Sandbox Code Playgroud)

(实际上,拥有m_sizem_data公开是一个坏主意,因为它们被捆绑在一起而你不想让人们搞乱它们.我也会在元素类型上模拟该类,即T代替int和使用Array<int>)

现在,您可以以非常直接的方式实现您的功能:

void function(Array& array)
{
    Array temp { array }; // this uses the copy constructor

    // do heavy processing on `temp`...

    std::swap(array, temp); // a regular assignment would copy
}
Run Code Online (Sandbox Code Playgroud)