使用动态数组复制构造函数和析构函数

时间:2018-03-31 00:53:09

标签: c++ constructor destructor copy-constructor

我一直致力于一个项目,我应该使用动态数组重新创建函数的基础知识。程序应该有一个默认的构造函数,它创建一个大小为2的数组,并且"向量"的大小为0,直到更多的值被添加到名为DynArray的向量类中。当数组处于容量状态时尝试将.push_back转换为向量时,我的程序应该以2倍的容量创建一个新的数组,并删除旧数组。这是我到目前为止所做的,我正在努力弄清楚应该如何设置复制构造函数以使其正常工作。

我一直在努力获取push_back和复制构造函数之间跳跃 当我在同一时间碰到一堵墙时,工作正常。

#include <iostream>
using namespace std;

class DynArray
{
   public:
      DynArray();
      DynArray(const DynArry& origClass);
      ~DynArray();
      int capacity();
      int size();
      void push_back(int newNum);
      int at(int atNum);

   private:
      int arraySize;
      int arrayCapacity;
      int newNum;
      int pushCounter;
      int atNum;
      int i;
      int arrayVector [];
};


DynArray::DynArray() // default constructor, creates array with no elements and capacity 2
{
   int* arrayVector = new int[2];
   arrayCapacity = 2;
   arraySize = 0;
   pushCounter = 0; // used for push_back, increments through array every time a new number is added with push_back
   return;
}

DynArray::DynArray(const DynArray& origClass) // copy constructor
{
   cout << "Copy Constructor Called." << endl;
   int* arrayVector = new int[2];
   *arrayVector = *(origClass.arrayVector)

   return;
}

void DynArray::push_back(int newNum)
{
   if (arraySize == arrayCapacity) // if the capacity is the same as the current size, make a new array with twice the capacity, copy over values, delete the old array
   {
      arrayCapacity = arrayCapacity * 2;
      int* newarrayVector = new int[arrayCapacity];
      for (i = 0; i < arraySize; ++i)
      {
         *newarrayVector [i] = arrayVector[i];
      }      
   arrayVector [pushCounter] = newNum; // push value to the next open value in the array
   ++arraySize; // increment so next push_back uses the following value
   ++pushCounter;
}

3 个答案:

答案 0 :(得分:0)

您的复制构造函数可以访问它正在复制的对象的私有成员,因此它应该与您的resize方法非常相似。有快捷方式(memcpy,std :: copy)但你最好学习如何使用循环。

所以,你有一些小问题:

  • 在复制构造函数中,将大小设置为与原始对象相同的大小。 (尽管如此,您可能会将其缩小为arraySize)。
  • 使用循环或批量复制功能(memcpy)复制所有元素
  • 你在push_back方法中缺少一个}
  • pushCounter始终与arraySize完全相同。你并不需要两者
  • 我应该是一个局部变量,而不是一个类成员。
  • 不使用班级成员atNum和newNum。

答案 1 :(得分:0)

几个明显的错误:

DynArray(const DynArry& origClass);
                     ^

这可能是一个错字。没有DynArry这样的类型。

 int arrayVector [];

该成员声明形成不良。您不能拥有未指定大小的成员数组。由于您正在重新实现动态数组,因此可能应该是一个指针来保存动态分配的数组的地址。指针声明如下:

  int* arrayVector;
int* arrayVector = new int[2];

这将动态数组的地址存储在本地自动变量中。一旦构造函数结束,指针 - 自动 - 就会被销毁并且数组被泄露。您可能应该对this->arrayVector进行更改。

*arrayVector = *(origClass.arrayVector)

这只复制数组的第一个元素。复制构造函数应该复制所有元素。为此,您还应该构建一个与您要复制的动态数组一样大的动态数组。

此外,复制构造函数会使许多成员未初始化(例如arraySize)。

 *newarrayVector [i] = arrayVector[i];

这个表达形式错误。您不能对整数使用间接操作。您可能打算分配给数组元素:

newarrayVector [i] = arrayVector[i];

除此之外,您的重新分配会遇到与构造函数相同的问题。当函数结束时,新数组就会被泄露,因为你没有将它存储在一个成员中。

*arrayVector = *(origClass.arrayVector)

return;

这个表达形式错误。你可能忘记了分号。

答案 2 :(得分:0)

您的复制构造函数应该复制传递给它的对象。

相反,它会这样做;

DynArray::DynArray(const DynArray& origClass) // copy constructor
{
    cout << "Copy Constructor Called." << endl;
    int* arrayVector = new int[2];
    *arrayVector = *(origClass.arrayVector);   // missing ; added here

    return;
}

忽略输出到cout,两个明显的问题是arrayVector动态分配了两个元素,无论origClass.arrayVector中有多少元素。

语句int *arrayVector = *(origClass.arrayVector)也根本不复制数组。

  • 首先,它会创建一个名为arrayVector的指针(与DynArray的成员无关,尽管名称相同)。
  • 然后复制origClass.arrayVector第一个元素(a 单int}到arrayVector第一个元素。就是这样 功能上等同于arrayVector[0] = origClass.arrayVector[0]。这就是指针的工作方式。
  • 最后,当构造函数返回时,声明的arrayVector不再存在,因为if是构造函数体的局部。结果是动态分配的内存被泄露(没有变量,或者DynArray类的成员,完全引用它,所以在标准C ++中没有办法在后续代码中找到该内存)。

最后,您的复制构造函数不会复制origClassarraySizearrayCapacitynewNumpushCounteratNum的任何其他成员,i) 到正在构建的新对象。

相反,您(通常)需要做的是复制所有成员,而不仅仅是其中一个成员。并且,如果被复制的成员之一是动态分配的数组 - 在您的情况下 - 构造函数需要首先构造一个新数组,然后将所有元素复制到它 - 一次一个,在某种形式的循环中。

例如,你可以做

DynArray::DynArray(const DynArray& origClass) // copy constructor
{
    arrayVector = new int[origClass.arrayCapacity];

这实际上修改了arrayVector的{​​{1}}成员(而不是声明一个局部变量)。它还使该指针指向动态分配的数组,其大小与DynaArray中相同。

这还没有完成从origClass复制数据。如上所述,使用origClass.arrayVector无法做到这一点。相反,构造函数需要执行此操作

*arrayVector = *(origClass.arrayVector)

此步骤对于确保复制 for (int i = 0; i < origClass.arrayCapacity; ++i) arrayVector[i] = origClass.arrayVector[i]; 的所有元素至关重要。这有多少变化(例如使用指针语法而不是数组语法),但上面就足够了。

然后有必要从origClass.arrayVector复制所有其他成员。

origClass

顺便说一下,让我感到震惊,你已经给了 arraySize = origClass.arraySize; arrayCapacity = origClass.arrayCapacity; newNum = origClass.newNum; pushCounter = origClass.pushCounter; atNum = origClass.atNum; i = origClass.i; } // the body of the constructor ends here. 一些他们不需要的成员。这些成员中的一些仅作为特定成员函数的临时值(例如循环计数器)而需要。这样做意味着DynArray的每个实例都有自己的变量副本。这是不必要的 - 它们最好是局部变量,在需要它们的每个函数中声明。

现在,上面的(有点)工作,但需要改进。在可能的情况下,最好在构造函数中使用初始化程序,并使构造函数体只执行在初始化程序中无法完成的操作。这样做有很多好处,但你可以做功课来找出它们是什么。

因此,最后,我将实现复制构造函数

DynArray

除了我之前的旁白,您有不必要的班级成员,此处的初始化列表仍会复制您的所有DynArray::DynArray(const DynArray& origClass) : // initialiser list begins here arrayVector(new int[origClass.arrayCapacity]), arraySize(origClass.arraySize), arrayCapacity(origClass.arrayCapacity), newNum(origClass.newNum), pushCounter(origClass.pushCounter), atNum(origClass.atNum), i(origClass.i) { // body of constructor starts here for (int i = 0; i < origClass.arrayCapacity; ++i) arrayVector[i] = origClass.arrayVector[i]; } 成员。

请注意,复制数组元素的循环位于构造函数的主体中,因为在初始化列表中无法轻松完成此类操作。

另请注意,变量DynArray(构造函数体中的循环计数器)与名为i的{​​{1}}成员没有关系。

最后,DynArray

的成员
i

会更好地声明为指针。它实际上不是一个数组。

DynArray