c++ - 移动构造函数中的深拷贝

标签 c++ c++11

我是 C++11 的新手,所以我仍然在为它的概念苦苦挣扎。

这是我的问题:

我有一个矩阵类:

class matrix
{

private:

  double** data;
  size_t number_lines;
  size_t number_columns;

  size_t capacity_lines;
  size_t capacity_columns;

public:
....

}

并且我提供了一个复制构造函数、一个移动构造函数...

我重载了乘法运算符 *(double x) 以将矩阵元素乘以标量 x 并返回乘积矩阵。 这是代码:

matrix matrix::operator*(double lambda)
{
double** aux_data = new double*[number_lines];
for (size_t i = 0; i < number_lines; i++)
{
    aux_data[i] = new double[number_columns];
    for (size_t j = 0; j < number_columns; j++)
        aux_data[i][j] = lambda*data[i][j];
}
return matrix(aux_data, number_lines, number_columns);
}

函数的返回值是一个右值引用,因此它调用了移动构造函数。这是移动构造函数的代码:

matrix::matrix(const matrix&& moved_copy)
{
if (this != &moved_copy) 
{
    number_columns = moved_copy.number_columns;
    number_lines = moved_copy.number_lines;
    data = moved_copy.data;
}
}

这个移动构造函数的问题在于它执行的是浅拷贝而不是深拷贝(就像我猜的每个移动构造函数一样,否则这个移动构造函数有什么意义)所以成员 data 指向到 moved_copy.data 指向的对象,但是这个对象是运算符 *=() 函数的本地对象,所以当运算符超出范围时,对象就消失了,我有一个悬空指针。所以我的问题是:我应该在移动构造函数中执行深层复制还是有没有办法在不这样做的情况下解决这个问题?

谢谢。

最佳答案

不,您不应该在移动构造函数中进行深度复制。移动构造函数的全部意义在于获取一些复制成本高昂的资源的所有权。

在这种情况下,您的 data 指针的所有权可以从现有的 matrix 转移到新构造的 matrix 对象。但想法是将所有权转移给新对象,而不是与新对象共享所有权。在这种情况下,这只是意味着将 moved_copy.data 设置为 nullptr,这样它就不会在销毁时删除您的 data

matrix::matrix(matrix&& moved_copy)
{
    number_columns = moved_copy.number_columns;
    number_lines = moved_copy.number_lines;
    data = moved_copy.data;
    moved_copy.data = nullptr;
}

请注意,我还删除了您的 if 守卫:无法从自身构造对象,因此移动构造函数并不真正需要它(尽管它对移动赋值运算符很有用) .

我还从 moved_copy 中删除了 const。移动构造函数需要修改移出对象的状态以获取其资源的所有权,因此不能使用 const

编辑:它是actually possible从自身构造对象,但这并不是您真正需要防范的事情。

关于c++ - 移动构造函数中的深拷贝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42949372/

相关文章:

c++ - IUknown 派生接口(interface)上的虚拟析构函数

c++ - 如何对两个容器元组进行排序?

c++ - Linux getrusage() maxrss 最大驻留集大小不随分配增加 (C++)

c++ - 为什么我的网络 TCP/UDP 实现不起作用?

C++将文本写入文件,如何多行

c++ - 类实例的唯一标识

c++ - 在 C++ 中,如何将 32 位数字传递给 'int' 变量,而不会将 0x7FFFFFFF 以上的任何内容视为负数?

c++ - 在成员初始化列表中填充 std::array

C++0x lambda vs block

c++ - Microsoft VC++ PPL 和 sleep