C 析構 拷貝 賦值函式的乙個知識點

2021-10-02 13:01:39 字數 1547 閱讀 9328

眾所周知,c++的類如果沒有預設建構函式,會自動生成乙個。

同理,如果沒有複製建構函式即a::a(const a&){}這個函式 ,則系統也會自動生成乙個,但這個自動生成的複製建構函式不一定滿足我們的要求。

比如下面的例子:

classa~

a()}

;

其中我們定義了預設建構函式、另乙個過載版本的建構函式和析構函式。但是我們沒有定義複製建構函式,所以系統自動幫我們生成了乙個,作用大致可以理解為下面的函式:

a

(const a& another)

之後我們定義乙個函式f:

void

f(a x)

這個函式只有乙個a型別的引數,即該函式只把實參呼叫一次複製建構函式得到乙個臨時變數就退出,退出後會呼叫析構函式釋放臨時變數的空間。

我們執行下面**:

int

main()

得到:

實際呼叫f(x)時系統生成的預設複製建構函式簡單的把指標a的值賦給形參的a,即下面**的含義:

a

(const a& another)

所以x和f(x)構造的臨時變數的成員a都指向同一塊記憶體。

f(x)呼叫完畢後會呼叫析構函式把臨時變數釋放掉。所以這個臨時變數的a指標就會被delete。而這個臨時變數的a正好等於x的a。所以呼叫f(x)之後,x的成員a指向了一塊無效記憶體(圖中可以看到呼叫f(x)後x的成員a指向的記憶體資料發生了變化),這樣是相當不安全的!

如果我們在主函式後面加上一行a y(x); 則由於預設的複製建構函式為簡單的拷貝,所以y的成員a也等於x的成員a,二者都指向了無效記憶體!

上面這個例子的問題是:我們定義了自己的析構函式,但沒有定義複製建構函式和賦值運算子過載,所以在複製時不同例項的成員資料發生了重疊。並且複製而來的臨時變數的釋放會導致原本變數的資料的丟失。

c++primer上說,如果定義析構函式,就要把複製建構函式、賦值運算子過載全部定義,否則容易出現問題。

編寫類時的賦值運算子過載時,注意兩點:

1.自賦值能正常執行不報錯。

2.賦值運算子一般都集合了複製建構函式和析構函式二者的功能。

例子:

a&

operator=(

const a& x)

return

*this

;}

先建立乙個臨時變數,然後依次賦值成員變數的值到this的成員,最後返回當前例項的引用,這樣函式退出時temp也被自動析構釋放。當然這個例子是建立在已經寫好複製建構函式和析構函式的前提下,否則這個函式中 程式設計師應該自己寫好對應的功能。

c 建構函式 拷貝,賦值,析構

建構函式 可以參考 作用 為物件成員變數賦初始值。new運算子一起使用 注意 1.建構函式的命名必須和類名完全相同 2.沒有返回值,即不用在定義時加返回值型別 void int float之類的 3.建構函式不能被直接呼叫,必須通過new運算子在建立物件時才會自動呼叫 拷貝函式 可自定義 思路就是賦...

C 的構造 析構 賦值 拷貝函式比較

建構函式 析構函式與賦值函式是每個類最基本的函式。每個類只有乙個析構函式,但可以有多個建構函式 包含乙個拷貝建構函式,其它的稱為普通建構函式 和 多個賦值函式 除了同類的賦值以外,還有其他的賦值方法 對於任意乙個類a,如果不想編寫上述函式,c 編譯器將自動為a產生四個預設的函式,如 a void 預...

C 的構造 析構 賦值 拷貝函式比較

建構函式 析構函式與賦值函式是每個類最基本的函式。每個類只有乙個析構函式,但可以有多個建構函式 包含乙個拷貝建構函式,其它的稱為普通建構函式 和多個賦值函式 除了同類的賦值以外,還有其他的賦值方法 對於任意乙個類a,如果不想編寫上述函式,c 編譯器將自動為a產生四個預設的函式,如 a void 預設...