簡體   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