【问题标题】:C++ Deep copy of dynamic array through assignment operatorC++ 通过赋值运算符深拷贝动态数组
【发布时间】:2019-10-05 01:18:19
【问题描述】:

我正在尝试将动态分配的数组复制到实例。我的代码似乎正在复制这些值,但它还需要调整数组的大小以匹配“&other”大小的数组。

关于代码的一些信息:手头有两个类,一个是“电影”,它以标题、电影时间和导演(所有指针)作为私有成员。还有一个叫做“MovieCollection”的数组,它是一个数组,将“Movie”的每个实例存储在给定的索引中。

//These are private member variables:`

int ArrySize = 50; //There is another section of code that points to this and resizes if needed, I believe it needed a size at runtime though.

//Array to store instance of "movie"
Movie *movieArry = new Movie[ArrySize];

//This is assignment operator
const MovieCollection& operator=(const MovieCollection& other)
{ 
  delete []movieArray;
  int otherSizeArry = other.ArrySize;
  Movie* temp;
  temp = new Movie[otherSizeArry];

  for (int i = 0; i < otherSizeArry; i++)
  temp[i] = other.movieArry[i];

  return *this;
  delete []temp;
}

在创建实例时,我使用了我编写的另一个函数来调整数组的大小。例如,我要复制的实例有 10 个索引,但我尝试将值复制到的新实例仍然有 50 个限制。据我了解,我必须删除它,因为数组无法调整大小,然后复制新的大小(连同值)。

任何帮助将不胜感激,并在此先感谢您。另外,如果需要更多代码,请见谅。我不想提供超出需要的东西。

【问题讨论】:

  • 只需使用std::vector。尝试手动管理这样的阵列是没有意义的。代码也存在多个问题,但很难评论,因为它不像发布的那样有效/可编译。您正在删除movieArray before 复制它(未定义的行为和use-after-free),并在返回后尝试删除temp,它永远不会被执行(泄漏),并且您永远不会分配复制的数组到任何东西。
  • 在赋值运算符中,movieArray被删除后需要赋值给某物。如movieArray = temp在return语句之前。如果您没有正确编码,这些事情就不会发生。

标签: c++ arrays dynamic-arrays delete-operator


【解决方案1】:

您的赋值运算符实现不正确。它在分配新的temp 数组之前释放movieArray 数组。如果分配失败,则该类将处于不良状态。而且在调用return *this; 之前,您没有将temp 数组分配给movieArray(永远不会到达delete []temp,编译器应该已经警告过您)。

运算符应该看起来更像这样:

MovieCollection& operator=(const MovieCollection& other)
{ 
    if (&other != this)
    {
        int otherSizeArry = other.ArrySize;
        Movie* temp = new Movie[otherSizeArry];

        for (int i = 0; i < otherSizeArry; ++i) {
            temp[i] = other.movieArry[i];
        }
        // alternatively:
        // std::copy(other.movieArry, other.movieArry + otherSizeArry, temp);

        std::swap(movieArray, temp);
        ArrySize = otherSizeArry;

        delete[] temp;
    }

    return *this;
}

如果你的类有一个拷贝构造函数(它应该——如果没有,你需要添加一个),赋值运算符的实现可以大大简化:

/*
MovieCollection(const MovieCollection& other)
{
    ArrySize = other.ArrySize;
    movieArray = new Movie[ArrySize];

    for (int i = 0; i < ArrySize; ++i) {
        movieArray[i] = other.movieArry[i];
    }
    // alternatively:
    // std::copy(other.movieArry, other.movieArry + ArrySize, movieArray);
}
*/

MovieCollection& operator=(const MovieCollection& other)
{ 
    if (&other != this)
    {
        MovieCollection temp(other);
        std::swap(movieArray, temp.movieArray);
        std::swap(ArrySize, temp.ArrySize);
    }

    return *this;
}

【讨论】:

  • 谢谢你,雷米!由于我仍在学习,因此非常感谢您的解释。我确实有一个问题,为什么最后实施“ArrySize = otherSizeArry”?不应该在复制值之前确定数组的大小吗?还是没关系?
  • @Brian 我更喜欢在指向数据的指针成功更新后更新大小。只要指针仍然指向旧数据,大小就应该反映旧大小
猜你喜欢
  • 2019-10-25
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-28
  • 1970-01-01
  • 2013-06-19
相关资源
最近更新 更多