[英]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),但是最好學習如何使用循環。
因此,列出一些小問題:
幾個明顯的錯誤:
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 ++中沒有辦法在后續代碼中找到該內存)。 最后,你的拷貝構造函數沒有任何其他成員復制origClass
( arraySize
, arrayCapacity
, newNum
, pushCounter
, atNum
, i
)給新的對象正在興建。
相反,您(通常)需要做的是復制所有成員,而不僅僅是其中一個。 而且,如果要復制的成員之一是動態分配的數組(如您的情況),則構造函數需要首先構造一個新數組,然后將所有元素復制到該數組中,一次以某種形式循環。
例如,您可以
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
(構造函數主體中的循環計數器)與名為i
的DynArray
成員沒有關系。
最后, DynArray
的成員
int arrayVector [];
最好聲明為指針。 它實際上不是數組。
int *arrayVector;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.