為物件動態分配記憶體
阿新 • • 發佈:2018-12-04
如果類中的資料成員含有指標變數,就需要為指標變數分配動態記憶體。(通常在程式設計中,應該儘量避免使用指標,應該用容器替代指標)
在本例中,使用二重指標,可以視為一個二維陣列,不過該陣列的元素個數可變。
如下為為指標分配空間的建構函式;
//建構函式,建立一個可以指定長度和高度的二維陣列 SpreadSheet::SpreadSheet(int height, int length) { mCells = new SpreadCell* [length]; for(int i = 0; i < length; i++) { mCells[i] = new SpreadCell[height]; } }
在此建構函式中,想為指標陣列分配空間,在為每個指標陣列中的元素分配空間。
釋放指標空間的解構函式定義如下:
//解構函式,先刪除length個一維指標,再刪除一個二維指標
SpreadSheet::~SpreadSheet()
{
for(int i = 0; i < length; i++)
{
//mCells[i]是指標陣列首地址,刪除此指標陣列中的所有元素。
delete [] mCells[i];
}
delete mCells;
}
由於mCells[i]相當於一個指標陣列的頭地址,mCells[i][0-j]都對應一個元素,所以刪除該指標使用了刪除陣列指標的方法
delete [] mCells
刪除指標陣列之後,再刪除該指向該指標陣列的指標mCells。
預設情況下,在含有指標陣列的物件中,物件的複製是淺複製,容易形成野指標。避免這種情況的話,就要在物件複製之前,先為物件分配空間,進行深複製。物件的賦值與此類似。以下程式碼為物件的複製操作。
//複製建構函式
SpreadSheet::SpreadSheet(const SpreadSheet& src)
{
copyFrom(src);
}
其中,copyFrom(src)為輔助函式,不僅分配記憶體,還為記憶體裡的元素賦值。其定義如下:
//輔助copy函式 void SpreadSheet::copyFrom(const SpreadSheet& src) { height = src.height; length = src.length; //分配length個堆空間,每個堆空間儲存一個指向SpreadCell的指標 mCells = new SpreadCell* [length]; for (int i = 0; i < length; i++) { //分配height個堆空間,每個堆空間儲存一個SpreadCell物件。 mCells[i] = new SpreadCell[height]; } for(int i = 0; i < length; i++) { for(int j = 0; j < height; j++) { mCells[i][j] = src.mCells[i][j]; } } }
上述程式碼就是先為本物件分配空間,在給物件內的空間賦值,很容易理解。如下為物件賦值的定義,在copyFrom之前,先進行了自賦值判斷。
//物件賦值
SpreadSheet& SpreadSheet::operator =(const SpreadSheet& rhs)
{
if(this == &rhs)
{
return *this;
}
else
{
copyFrom(rhs);
return *this;
}
}
整體程式如下所示:
#include <iostream>
#include <string>
using namespace std;
class SpreadCell
{
private:
int value;
public:
SpreadCell(): value(0) {};
SpreadCell(int a): value(a) {};
void setValue(const int& a);
int getValue() const;
};
//賦值給其它值的形參都可以這樣定義
void SpreadCell::setValue(const int &a)
{
value = a;
}
//const的作用,保證該函式不修改資料成員
int SpreadCell::getValue() const
{
return value;
}
class SpreadSheet
{
private:
int height;
int length;
SpreadCell **mCells;
void copyFrom(const SpreadSheet &src);
public:
//~ SpreadSheet();
SpreadSheet(int height = 4, int length = 5);
SpreadSheet(const SpreadSheet& src);
virtual ~SpreadSheet();
SpreadSheet& operator = (const SpreadSheet& rhs);
void setValue(const int& x, const int& y, const SpreadCell& cell);
SpreadCell getValue(const int& x, const int& y);
};
//建構函式,建立一個可以指定長度和高度的二維陣列
SpreadSheet::SpreadSheet(int height, int length)
{
mCells = new SpreadCell* [length];
for(int i = 0; i < length; i++)
{
mCells[i] = new SpreadCell[height];
}
}
//輔助copy函式
void SpreadSheet::copyFrom(const SpreadSheet& src)
{
height = src.height;
length = src.length;
//分配length個堆空間,每個堆空間儲存一個指向SpreadCell的指標
mCells = new SpreadCell* [length];
for (int i = 0; i < length; i++)
{
//分配height個堆空間,每個堆空間儲存一個SpreadCell物件。
mCells[i] = new SpreadCell[height];
}
for(int i = 0; i < length; i++)
{
for(int j = 0; j < height; j++)
{
mCells[i][j] = src.mCells[i][j];
}
}
}
//複製建構函式
SpreadSheet::SpreadSheet(const SpreadSheet& src)
{
copyFrom(src);
}
//物件賦值
SpreadSheet& SpreadSheet::operator =(const SpreadSheet& rhs)
{
if(this == &rhs)
{
return *this;
}
else
{
copyFrom(rhs);
return *this;
}
}
//解構函式,先刪除length個一維指標,再刪除一個二維指標
SpreadSheet::~SpreadSheet()
{
for(int i = 0; i < length; i++)
{
//mCells[i]是指標陣列首地址,刪除此指標陣列中的所有元素。
delete [] mCells[i];
}
delete mCells;
}
//在指定位置定義元素
void SpreadSheet::setValue(const int& x, const int& y, const SpreadCell& cell)
{
mCells[x][y] = cell;
}
//讀取指定位置的元素
SpreadCell SpreadSheet::getValue(const int& x, const int& y)
{
return mCells[x][y];
}
int main()
{
SpreadCell a, cell;
a.setValue(2);
SpreadSheet sc(4, 5);
sc.setValue(1, 2, a);
cell = sc.getValue(1, 2);
SpreadSheet sc2(sc), sc3;
sc3 = sc;
cout << "value:" << cell.getValue() << endl;
}