繁体   English   中英

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

[英]Copy Constructor and Destructor with a Dynamic Array

我一直在从事一个项目,在该项目中我应该使用动态数组来重新创建函数的基础。 该程序应具有默认的构造函数,该构造函数将创建一个大小为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;
}

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

因此,列出一些小问题:

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

几个明显的错误:

 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; 

此表达式格式错误。 您可能忘记了分号。

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

相反,它做到了;

 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 (单个int )到的第一个元素 arrayVector 因此,它在功能上等效于arrayVector[0] = origClass.arrayVector[0] 这就是指针的工作方式。
  • 最后,当构造函数返回时,声明的arrayVector不再存在,因为if对于构造函数的主体是局部的。 结果是动态分配的内存被泄漏(根本没有变量或DynArray类的成员引用它,因此标准C ++中没有办法在后续代码中找到该内存)。

最后,你的拷贝构造函数没有任何其他成员复制origClassarraySizearrayCapacitynewNumpushCounteratNumi )给新的对象正在兴建。

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

例如,您可以

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

这实际上改变了arrayVector所述的构件DynaArray (而不是声明一个局部变量)。 它还使该指针指向动态分配的数组,该数组的大小与origClass大小相同。

这还没有完成,就是从origClass.arrayVector复制数据。 *arrayVector = *(origClass.arrayVector)我在上面提到的,使用*arrayVector = *(origClass.arrayVector)无法完成此操作。 相反,构造函数需要这样做

   for (int i = 0; i < origClass.arrayCapacity; ++i)
       arrayVector[i] = origClass.arrayVector[i];

此步骤对于确保复制origClass.arrayVector所有元素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每个实例都有自己的那些变量副本。 那是不必要的-它们最好是局部变量,在需要它们的每个函数中声明。

现在,以上将(某种)工作,但是需要改进。 通常最好在构造函数中使用初始化程序,并让构造函数主体仅执行初始化程序中无法完成的工作。 这样做有很多优点,但是您可以做作业以弄清它们是什么。

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

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 (构造函数主体中的循环计数器)与名为iDynArray成员没有关系。

最后, DynArray的成员

int arrayVector []; 

最好声明为指针。 它实际上不是数组。

int *arrayVector; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM