第一次看c++ primer時拷貝控制這章完全沒看明白,只是很粗略地過了一遍。時隔一年,具備了一定的工程經驗後,再次看這一章對於類的拷貝構造/賦值函式、移動構造/賦值函式以及析構函式有了完全不一樣的認識,在部落格裡記錄一下,c++ primer每看一遍都會有不同的收穫倒真不是亂說。
拷貝建構函式第乙個引數必須是乙個引用型別,且通常是乙個const的引用。另外,拷貝建構函式會在很多情況下被隱式地使用,不應該為explicit函式。當我們沒有顯式地定義乙個拷貝建構函式時,編譯器會為我們定義乙個,當然這個函式是不是符合我們的預期是存疑的。
拷貝建構函式在以下情況被使用到:
與拷貝建構函式一樣,類通過拷貝賦值函式對物件進行賦值,如果類未定義自己的拷貝賦值運算子,編譯器會為它合成乙個。
析構函式主要的目的是釋放物件在生存期內分配的資源,並銷毀非static成員。同樣在未自定義析構函式時,編譯器會定義乙個合成析構函式。
析構函式被呼叫的情況:
c++語言雖然沒有要求我們定義所有的這些操作,但是這三個操作通常需要作為乙個整體來進行定義,下面給出原因
設計類時,首先考慮的是應不應該為其自定義乙個析構函式,從而避免某些類物件在使用預設析構函式時沒有釋放類中動態分配的記憶體,造成記憶體洩漏。
舉個書裡的例子
class
hasptr
~hasptr()
private
: std::string* ps;
int i;
}//對這個類進行處理的函式
hasptr f
(hasptr hp)
物件移動操作是在c++ 11新標準中新增的,在一些應用場景中,某些物件在拷貝完之後就被銷毀了,當物件過大時,移動而非拷貝物件會顯著地提公升程式的效能。
為了支援移動操作,c++ 11標準新增了乙個新的引用型別–右值引用。關於左值和右值,簡單地說,左值是乙個物件的身份,而右值是乙個具體的值;左值持久,右值短暫。因此,右值引用只能繫結到臨時物件,包括:即將被銷毀的物件以及沒有其他使用者的物件。這也就意味著右值引用的**可以自由地接管所引用物件的資源
類似拷貝建構函式,移動建構函式第乙個引數是該型別的乙個右值引用,同時,在完成移動建構函式之後,源物件不能再指向被移動的資源,必須確保源物件處於銷毀無害的狀態。
strvec::
strvec
(strvec &&s)
noexcept
//移動操作不丟擲異常
//成員初始化,接管s中的資源
:elements
(s.elements)
,first_free
(s.first_free)
,cap
(s.cap)
移動賦值操作與移動建構函式執行相同的工作,同時需要考慮並正確處理自賦值
作者總結了c++拷貝控制的內容,將其濃縮成三/五準則。其中,」五「指的是所有的五個拷貝控制成員應該看作乙個整體,乙個類定義了任何乙個操作,就應該定義所有的五個操作。」三「指的是拷貝初始化、拷貝賦值以及析構函式這三者之間的相互關係,某些類必須同時具有這三個操作才能正確工作。另外,雖然移動操作可以避免拷貝過程額外的開銷,可以大幅度提公升效能,但是移後源物件具有不確定的狀態,不安全的移動操作可能會導致莫名其妙的錯誤,需要慎用。
類的拷貝 賦值與銷毀
拷貝建構函式 拷貝賦值運算子 移動建構函式 移動賦值運算子 析構函式 當定義乙個類時,我們顯式和隱式地指定在此型別物件的拷貝 移動 賦值和銷毀時做些什麼。而乙個類通過定義上述五種特殊的成員函式來控制這些操作。拷貝和移動建構函式定義了當同型別的另乙個物件初始化本物件時做什麼。拷貝和移動賦值運算子定義了...
C 中的拷貝構造,賦值和移動構造
在說明這幾個名詞時,我們需要定義乙個測試類person,person類的測試環境為vs2013 一般情況下,在物件宣告時用拷貝建構函式對物件進行初始化 在編譯器進行優化的時候也會使用移動構造函 數 在有臨時物件產生的情況下 這樣效率會高一些,如避免深度拷貝之類的操作 一旦初始化之後,在 進行 運算將...
C 類的賦值和拷貝
include stdafx.h include include class a a a int id,char username id id username username a a a 過載拷貝函式 a operator a b 過載賦值函式,形參為引用,避免了一次物件的拷貝構造 或者 我們也...