13.1.2拷貝賦值運算子
13.1.3析構函式
13.1.4三/五法則
13.1.5使用=default
13.1.6阻止拷貝
13.2拷貝控制和資源管理
13.2.2定義行為像指標的類
13.3交換操作
13.4拷貝控制示例
13.5動態記憶體管理類
13.6物件移動
13.6.2移動建構函式和移動賦值運算子
13.6.3右值引用和成員函式
本章學習的目的:能夠指定乙個類物件在執行拷貝、移動、賦值和銷毀時具體做什麼乙個類通過特殊成員函式來執行這些操作,稱為拷貝控制操作, 共五個如下:
注意:這五個操作如果不定義,編譯器會自動定義
classname (
const classname&
);
第乙個引數幾乎總是const的引用合成拷貝建構函式多種情況會被隱式引用,拷貝建構函式不應該是explicit的,不能禁止隱式轉換
拷貝初始化
//直接初始化,實際上是要求編譯器使用普通的函式匹配來選擇最匹配的建構函式,例如:
string dot(10
,'s)
;
//拷貝初始化,要求編譯器將右側物件拷貝到正在建立的物件中,有需要的話進行型別轉換,通常由拷貝建構函式完成,也可以使用移動建構函式
//例如:
string s2 = dots;
此外拷貝初始化不僅在=時發生,也會發生在:
實參傳給非引用形參;
函式返回非引用物件;
花括號列表初始化陣列或聚合類成員。
引數和返回值
拷貝初始化的限制
//vector接收單一大小引數的建構函式時explicit的
vector<
int>v1(
1);//正確 直接初始化
vector<
int> v2 =10;
//錯誤×
void
f(vector<
int>);
//引數是拷貝初始化f(
10);//錯誤
f(vector<
int>(10
));//正確 構造臨時變數
過載賦值運算子
合成拷貝賦值運算子
sales_data trans, accum;
trans = accum;
//使用sales_data的拷貝賦值運算子
//這個定義的拷貝賦值函式等價於合成拷貝賦值運算子
sales_data& sales_data::
operator=(
const sales_data &rhs)
~
classname()
;//析構函式唯一
析構函式完成什麼工作
合成析構函式定義刪除的函式
private拷貝控制
類值拷貝賦值運算子
classname& classname::
operator=(
const classname& rhs)
引用計數classname& classname::
operator=(
const classname& rhs)
ps = rhs.ps;
i = rhs.i;
//內建型別(不包含指標)本身就是值
use = rhs.use;
return
*this
;}
message
folders
簡單實現vector的簡化版本,不使用模板,只使用string,命名為strvec
strvec類的設計
為了獲得可以接受的效能,vector預先分配一定的空間,每個新增元素的成員函式都會先檢查是否可以容納,如果有則繼續,否則就會重新分配空間,將已有元素移動到新空間中,釋放舊的空間,新增新的元素。
strvec需要的功能:strvec類定義elements 指向分配的記憶體中的首元素
first_free 指向最後乙個實際元素之後的位置
cap 指向分配的記憶體末尾之後的位置
靜態成員alloc,型別是allocator
alloc_n_copy 分配記憶體,並拷貝乙個給定範圍內的元素
free 會銷毀構造的元素並釋放記憶體
chk_n_alloc保證strvec中至少有容納乙個新元素的空間
reallocate在記憶體用完時分配新記憶體
strvec
左值持久;右值短暫
變數是左值
int
&&rr1 =43;
int&&rr2 = rr1;
//錯誤❌,rr1是變數,是左值
標準庫move函式//使用move意味著希望像右值一樣處理乙個左值,
//承諾我們不再使用rr1,僅作賦值或銷毀
int&&rr3 = std::
move
(rr1)
;
strvec::
strvec
(strvec &&s)
noexcept
:elements
(s.elements)
,first_free
(s.first_free)
,cap
(s.cap)
//避免編譯器做為了處理丟擲異常的額外操作,我們使用noexpect通知指明不丟擲異常
移動賦值運算子
移後源物件必須可析構
合成的移動操作
移動右值,拷貝左值
拷貝並交換賦值運算子和移動操作
移動迭代器
由於乙個移後源物件具有不確定的狀態,因此對其呼叫std::move是危險的,當我們使用移動操作必須確定移後源物件沒有其他使用者。
一般允許移動的成員函式通常使用乙個版本接收指向const的左值引用,第二個版本接收指向非const的右值引用。
void
push_back
(const t&);
void
push_back
(t&&
);
右值和左值引用成員函式//只可向可修改的左值賦值
classname &
operator=(
const classname&)&
;
過載和引用函式//只可向可修改的左值賦值
classname &
operator=(
const classname&)&
;
過載和引用函式 C Primer 第十三章 拷貝控制
當定義乙個類時,我們顯式或隱式指定在此型別的物件執行拷貝,移動,賦值,銷毀時做什麼,通過拷貝建構函式,拷貝賦值運算子,移動建構函式,移動賦值運算子和析構函式。拷貝賦值與銷毀 如果建構函式的第乙個引數是自身類型別的引用,並且其他引數都有預設值,則此建構函式是拷貝建構函式。第乙個引數一定是引用型別,並且...
C Primer 第十三章 複製控制
複製建構函式 賦值操作符和析構函式總稱為複製控制。編譯器自動實現這些操作,但類也可以定義自己的版本。複製建構函式是一種特殊建構函式,具有單個形參,該形參 常用 const 修飾 是對該類型別的引用。析構函式是建構函式的互補 當物件超出作用域或動態分配的物件被刪除時,將自動應用析構函式。不管類是否定義...
文字查詢程式(C primer5th)
書上的乙個比較簡單的例題,可以輸出文字中單詞總共出現的次數,所在的行數及所在行的內容。主要的思路是建立乙個vector來分行儲存文字,然後將單詞及單詞出現行數 set 建立乙個map。通過查詢單詞獲得其對映的set。set的size為出現的次數,set的元素為出現的行數,通過set元素作為vecto...