眾所周知,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 預設...