C Primer5th 第十三章 拷貝控制

2021-10-07 11:39:23 字數 4263 閱讀 4110

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需要的功能:

elements 指向分配的記憶體中的首元素

first_free 指向最後乙個實際元素之後的位置

cap 指向分配的記憶體末尾之後的位置

靜態成員alloc,型別是allocator

alloc_n_copy 分配記憶體,並拷貝乙個給定範圍內的元素

free 會銷毀構造的元素並釋放記憶體

chk_n_alloc保證strvec中至少有容納乙個新元素的空間

reallocate在記憶體用完時分配新記憶體

strvec類定義

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...