題目:下面是乙個陣列類的宣告與實現。請分析這個類有什麼問題,並針對存在的問題提出幾種解決方案。
template
class array
~array()
voidsetvalue(unsigned index, const t& value)
t getvalue(unsignedindex) const
private:
t* data;
unsignedsize;
};分析:這個類中有指標成員變數,在這種情況下,如果處理不當,很容易造成記憶體洩露問題。
該類沒有提供拷貝建構函式和賦值(=)運算子的過載函式,當需要呼叫拷貝建構函式或者賦值操作時,編譯器會自動呼叫系統生成的預設拷貝建構函式或者預設賦值運算子過載函式,而這兩個預設的函式是以逐個拷貝成員變數的方式來賦值資料成員,在這種拷貝方式下,賦值指標被定義為將乙個變數的位址賦給另乙個變數,也即兩個指標指向同乙個位址,這種隱式的指標複製結果就是兩個物件擁有指向同乙個動態分配的記憶體空間的指標。當釋放第乙個物件的時候,它的析構函式就會釋放與該物件有關的動態分配的記憶體空間。而釋放第二個物件的時候,它的析構函式會釋放相同的記憶體,這樣是錯誤的(
兩次釋放同一塊記憶體是錯誤的做法,而且很可能造成堆的奔潰)。
所以,如果按如下方式呼叫就會出現記憶體洩露問題:
arraya(20);
arrayb(a); 或者
arraya(20);
arrayb(10);
a = b;
編譯器會自動呼叫預設拷貝建構函式和預設賦值運算子過載函式,而這兩個預設的函式對指標都是按位拷貝,只拷貝位址,而不會把指標所指向的內容做拷貝,因此當a.data和b.data指向同一位置,當a或者b中任意乙個結束生命週期時,就會delete data,由於a和b指向的是同一位置,所以兩個例項的data都被delete了,所以會出現兩次釋放同一片記憶體空間的問題,這樣的做法是錯誤的。
解決方案1: 禁用拷貝建構函式和賦值運算子過載函式
private:
array(const array& array);const array& operator=(
const array& array);
解決方案2:新增拷貝建構函式和賦值運算子過載函式,並且合理的實現。
public:
array(const array& array);const array& operator=(const array& array);
template
array::array(const array&array): data(0), size(array.size)
}template
const array& array::operator=(const array& array)
size = array.size;}if(size > 0)
解決方案3:用引用計數來管理指標成員
public:
array(const array& array);
const array& operator=(const array& array);
template
array::array(unsignedarraysize):data(0), size(arraysize)
template
array::array(const array&array): data(0), size(array.size), count(array.count)
template
const array& array::operator=(const array& array)
template
array::~array()
private:
void release()
}
}
因此,如果乙個類裡面有指標成員變數,要麼必須顯示的寫拷貝建構函式和過載賦值運算子,要麼禁用拷貝建構函式和過載賦值運算子。
含有指標成員的類的拷貝
題目 下面是乙個陣列類的宣告與實現。請分析這個類有什麼問題,並針對存在的問題提出幾種解決方案。1 templateclass array29 10 array 1114 15void setvalue unsigned index,const t value 1620 21 t getvalue u...
關於含有指標成員的類的物件之間賦值指標的問題。
在c 中,當定義了乙個類,類的成員中有指標的時候,需要注意 如果將類的物件a賦值給b的時候,兩個物件的指標是指向同乙個位址的,其餘的變數都是相等的。在影象處理中,比如定義了乙個影象類,類成員中有具體的影象資料,如果將兩個物件直接相等,會使兩個物件的資料指標指向同乙個位址。如果要使兩個物件的指向不同的...
函式返回含有指標成員的物件
移動構造 淺層複製只實現物件間的資料元素一一對應,只複製成員函式中的指標位址,如下圖 pointarray2複製了pointarray1,只複製了指標,pointarray2與pointarray1指向了同一塊陣列元素,在執行後進行記憶體釋放時會先呼叫pointarray1的析構函式釋放陣列記憶體,...