简体   繁体   English

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

[英]Copy Constructor and Destructor with a Dynamic Array

I've been working on a project in which I am supposed to recreate the basics of the function using a dynamic array. 我一直在从事一个项目,在该项目中我应该使用动态数组来重新创建函数的基础。 The program should have a default constructor, which creates an array with a size of 2, and the "vector"'s size is 0 until more values are added to the vector class, named DynArray. 该程序应具有默认的构造函数,该构造函数将创建一个大小为2的数组,并且“向量”的大小为0,直到将更多值添加到名为DynArray的向量类中。 When there's an attempt to .push_back into the vector when the array is at capacity, my program should make a new coppy of the array with 2x the capacity, and delete the old array. 当在阵列达到容量时尝试将.push_back插入向量时,我的程序应以2倍的容量对阵列进行新复制,并删除旧阵列。 This is what I have so far, and I'm struggling to figure out how the copy constructor should be set up so it works appropriately. 到目前为止,这就是我要做的事情,而且我正在努力找出应该如何设置复制构造函数,以便使其正常工作。

I've been jumping between working on getting push_back and the copy constructor working properly when I've run into a wall with either in the mean time. 我一直在努力使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;
}

Your copy constructor can access private members of the object it is copying, so it should be very much like your resize method. 复制构造函数可以访问正在复制的对象的私有成员,因此它应该非常类似于您的resize方法。 There are shortcuts (memcpy, std::copy) but you are better off learning how to use the loop. 有一些快捷方式(memcpy,std :: copy),但是最好学习如何使用循环。

So, list of little issues you have: 因此,列出一些小问题:

  • in copy constructor, set the size to the same size as the original object. 在复制构造函数中,将大小设置为与原始对象相同的大小。 (although, you could potentially shrink it to arraySize). (尽管您可以将其缩小为arraySize)。
  • copy all the elements using a loop or bulk copy function (memcpy) 使用循环或批量复制功能(memcpy)复制所有元素
  • You are missing a } in your push_back method 您在push_back方法中缺少}
  • pushCounter is always exactly the same as arraySize. pushCounter始终与arraySize完全相同。 You don't need both 你们都不需要
  • i should be a local variable, not a class member. 我应该是局部变量,而不是类成员。
  • The class members atNum and newNum are not used. 不使用atNum和newNum的类成员。

Few obvious bugs: 几个明显的错误:

 DynArray(const DynArry& origClass); ^ 

This is probably a typo. 这可能是拼写错误。 There is no such type as DynArry . 没有DynArry这样的类型。


  int arrayVector []; 

This member declaration is ill formed. 该成员声明格式错误。 You are not allowed to have member arrays of unspecified size. 不允许您使用未指定大小的成员数组。 Since you're re-implementing a dynamic array, this should probably instead be a pointer to hold the address of the dynamically allocated array. 由于您要重新实现动态数组,因此它可能应该是一个指针,用于保存动态分配的数组的地址。 A pointer is declared like this: 指针声明如下:

  int* arrayVector;

 int* arrayVector = new int[2]; 

This stores the address of the dynamic array in a local automatic variable. 这会将动态数组的地址存储在本地自动变量中。 As soon as the constructor ends, the pointer - being automatic - is destroyed and the array is leaked. 构造函数结束后,指针(即自动指针)将被破坏,并且数组将泄漏。 You should probably make the changes to this->arrayVector instead. 您可能应该改为this->arrayVector进行更改。


 *arrayVector = *(origClass.arrayVector) 

This copies only the first element of the array. 这仅复制数组的第一个元素。 The copy constructor should probably copy all of the elements. 复制构造函数可能应该复制所有元素。 To that end, you should also construct a dynamic array that is as big as the one you're copying from. 为此,您还应该构造一个动态数组,该数组与要复制的数组一样大。

Also, the copy constructor leaves many of the members uninitialized (such as arraySize ). 此外,复制构造函数还保留许多未初始化的成员(例如arraySize )。


  *newarrayVector [i] = arrayVector[i]; 

This expression is ill-formed. 此表达式格式错误。 You cannot use the indirection operation on an integer. 您不能对整数使用间接操作。 You probably intended to assign to the array element instead: 您可能打算改为分配给数组元素:

newarrayVector [i] = arrayVector[i];

Besides that, your reallocation suffers from the same problem as your constructors. 除此之外,您的重新分配遭受与构造函数相同的问题。 The new array is simply leaked when the function ends since you don't store it in a member. 当函数结束时,新数组只是泄漏,因为您没有将其存储在成员中。


 *arrayVector = *(origClass.arrayVector) return; 

This expression is ill-formed. 此表达式格式错误。 You may have forgotten a semicolon. 您可能忘记了分号。

Your copy constructor should make a copy the object passed to it. 您的副本构造函数应复制传递给它的对象的副本。

Instead it does this; 相反,它做到了;

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

Ignoring output to cout , the two obvious problems are that arrayVector is dynamically allocated with two elements, regardless of how many elements there are in origClass.arrayVector . 忽略输出到cout ,两个明显的问题是arrayVector动态分配了两个元素,而不管origClass.arrayVector有多少个元素。

The statement int *arrayVector = *(origClass.arrayVector) also does not copy an array at all. 语句int *arrayVector = *(origClass.arrayVector)也根本不复制数组。

  • First of all it creates a pointer named arrayVector (which is unrelated to the member of DynArray , despite having the same name). 首先,它创建一个名为arrayVector的指针(尽管具有相同的名称,该指针与DynArray的成员无关)。
  • Then it copies the first element of origClass.arrayVector (a single int ) to the first element of arrayVector . 然后将其复制的第一个元素 origClass.arrayVector (单个int )到的第一个元素 arrayVector So it is functionally equivalent to arrayVector[0] = origClass.arrayVector[0] . 因此,它在功能上等效于arrayVector[0] = origClass.arrayVector[0] That's the way pointers work. 这就是指针的工作方式。
  • Lastly, when the constructor returns, the arrayVector declared ceases to exist, because if is local to the body of the constructor. 最后,当构造函数返回时,声明的arrayVector不再存在,因为if对于构造函数的主体是局部的。 A consequence is that the dynamically allocated memory is leaked (no variables, or members of your DynArray class, refer to it at all, so there is no way in standard C++ to find that memory in subsequent code). 结果是动态分配的内存被泄漏(根本没有变量或DynArray类的成员引用它,因此标准C ++中没有办法在后续代码中找到该内存)。

Lastly, your copy constructor does not copy any other members of origClass ( arraySize , arrayCapacity , newNum , pushCounter , atNum , i ) to the new object being constructed. 最后,你的拷贝构造函数没有任何其他成员复制origClassarraySizearrayCapacitynewNumpushCounteratNumi )给新的对象正在兴建。

Instead, what you (typically) need to do is copy ALL of of the members, not just one of them. 相反,您(通常)需要做的是复制所有成员,而不仅仅是其中一个。 And, if one of the members being copied is a dynamically allocated array - as in your case - the constructor needs to first construct a new array, and THEN copy all elements to it - one at a time, in a loop of some form. 而且,如果要复制的成员之一是动态分配的数组(如您的情况),则构造函数需要首先构造一个新数组,然后将所有元素复制到该数组中,一次以某种形式循环。

For example, you could do 例如,您可以

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

This actually modifies the arrayVector member of the DynaArray (rather than declaring a local variable). 这实际上改变了arrayVector所述的构件DynaArray (而不是声明一个局部变量)。 It also makes that pointer point at a dynamically allocated array of the same size as in origClass . 它还使该指针指向动态分配的数组,该数组的大小与origClass大小相同。

What this hasn't done is copy data from origClass.arrayVector . 这还没有完成,就是从origClass.arrayVector复制数据。 AS I noted above, this cannot be done using *arrayVector = *(origClass.arrayVector) . *arrayVector = *(origClass.arrayVector)我在上面提到的,使用*arrayVector = *(origClass.arrayVector)无法完成此操作。 Instead the constructor needs to do this 相反,构造函数需要这样做

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

This step is essential to ensure ALL the elements of origClass.arrayVector are copied. 此步骤对于确保复制origClass.arrayVector所有元素origClass.arrayVector There are variations of HOW this is done (eg using pointer syntax rather than array syntax) but the above will suffice. 有多种方法可以做到这一点(例如,使用指针语法而不是数组语法),但是上面的内容就足够了。

Then it is necessary to copy all of the other members from origClass . 然后有必要从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.

As an aside, it strikes me you have given your DynArray a number of members it doesn't need. DynArray一句让我感到DynArray是,您为DynArray分配了许多不需要的成员。 Some of those members are only needed as temporaries in particular member functions (eg loop counters). 这些成员中的某些仅在特定成员函数(例如,循环计数器)中作为临时成员才需要。 Doing that means EVERY instance of DynArray has its own copy of those variables. 这样做意味着DynArray每个实例都有自己的那些变量副本。 That is unnecessary - they would be better off being local variables, declared in each function where they are needed. 那是不必要的-它们最好是局部变量,在需要它们的每个函数中声明。

Now, the above will (sort of) work, but needs to be improved. 现在,以上将(某种)工作,但是需要改进。 It is generally better to use initialisers in constructors where possible, and have the constructor body only do things that can't be done in initialisers. 通常最好在构造函数中使用初始化程序,并让构造函数主体仅执行初始化程序中无法完成的工作。 There are various advantages to doing this, but you can do homework to find out what they are. 这样做有很多优点,但是您可以做作业以弄清它们是什么。

In the end, therefore, I would implement the copy constructor as 因此,最后,我将复制构造函数实现为

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];
}

Not withstanding my previous aside that you have unnecessary members of the class, the initialiser list here still copies ALL of your DynArray members. 除了我之前没有提到过您没有该类的成员之外,此处的初始化程序列表仍会复制所有DynArray成员。

Note that the loop to copy array elements is in the body of the constructor, since that sort of thing cannot be done readily in an initialiser list. 请注意,复制数组元素的循环在构造函数的主体中,因为在初始化列表中无法轻松完成这种事情。

Also note that the variable i (the loop counter in the constructor body) has no relationship to member of DynArray named i . 还要注意,变量i (构造函数主体中的循环计数器)与名为iDynArray成员没有关系。

Lastly, the member of DynArray 最后, DynArray的成员

int arrayVector []; 

would be better declared as a pointer. 最好声明为指针。 It is not actually an array. 它实际上不是数组。

int *arrayVector; 

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

相关问题 带有复制构造函数的析构函数 - Destructor with copy constructor 复制构造函数,析构函数和临时函数 - copy constructor,destructor and temporaries 为什么析构函数和复制构造函数使用对象数组显示此行为? - Why destructor and copy constructor is showing this behavior with array of objects? 在MSVC上的数组初始化期间调用了没有复制或移动构造函数的析构函数 - Destructor called without copy or move constructor during array initialization on MSVC 奇怪的复制构造函数和析构函数错误 - Strange copy constructor and destructor error 如果存在析构函数,为什么会生成复制构造函数 - Why copy constructor is generated if there is a destructor C ++中的额外析构函数,复制构造函数,C ++中的析构函数序列 - Extra destructor in Constructor, Copy constructor, Destructor sequence in C++ 动态二维数组的复制构造函数 - Copy constructor of dynamic two-dimensional array 为类内的动态数组复制构造函数和operator = - Copy constructor and operator= for a dynamic array inside a class 如何在具有指向对象的指针的数组的类中创建复制构造函数和析构函数,其中对象本身具有指向int的指针的数组 - How to create copy constructor and destructor in a class with an array of pointers to objects where objects itself have an array of pointers to ints
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM