類通過5種特殊的成員函式:拷貝建構式(copy constructor)、拷貝賦值運算子(copy-assignment operator)、移動建構式(move constructor)、移動賦值運算子(move-assignment)和解構式(destructor),來完成物件的拷貝、移動、賦值和銷毀,
class Foo(){
public:
Foo();
~Foo();
Foo(const Foo&); //拷貝建構式
Foo& operator=(const Foo&); //拷貝賦值賦值運算子
}
拷貝建構式
- 即使定義了其他建構式,編譯器也會合成一個拷貝建構式,
- 合成拷貝建構式將逐個拷貝非static成員變數,
- 對類成員,使用其拷貝建構式、
- 對陣列,逐個拷貝(元素型別的拷貝建構式)
- 拷貝初始化通常通過 拷貝建構式 來完成
Foo a;
Foo b = a; //拷貝初始化
String s = "a"; //拷貝初始化
- 編譯器有時可以跳過拷貝/移動建構式
string s = "a"; //拷貝初始化
//可執行為
string s("a"); //直接初始化
拷貝賦值運算子
- 未定義則生成合成拷貝復制運算子,行為類似拷貝建構式
- 定義拷貝復制運算子時需要注意:如果一個物件賦予它自身時,必須能正常作業
- 使用swap的拷貝賦值運算子(拷貝并交換),自動處理了自賦值情況其是例外安全的,
Foo& operator=(Foo rhs){ //注意rhs不是參考!!
swap(*this, rhs);
return *this;
}
//結束時,結束時原來該物件中的資源,被rhs釋放
三/五法則
- 需要解構式的類也需要拷貝和賦值操作(需要拷貝/賦值操作 不一定 需要解構式)
- 需要拷貝操作的類也需要賦值操作,反之亦然
- 一般來說一個類定義了任何一個拷貝操作,它就應該定義所有五個操作,
使用=delete來阻止拷貝
- 不會生成合成的拷貝建構式/拷貝賦值運算子
Foo(const Foo&) = delete; //阻止拷貝
Foo& operator(const Foo&) = delete; //阻止賦值
- 洗掉了 解構式的類,不能定義該變數或創建其臨時變數,但可以動態分配,但無法釋放,
- 如果一個類的資料成員不能默認構造/拷貝/賦值/銷毀,則對應的合成的成員函式將被定義為洗掉的,
- 某個成員的解構式是洗掉的不可訪問的(如private)/類內有一個參考成員/類內有一個const成員且沒有類內初始化,則該該類合成的建構式被洗掉
swap
標準庫的swap,需要一次拷貝和兩次賦值,對于有類外資源的物件來說,更好的方式是交換指標,而不是拷貝, 為了優化,需自己定義swap,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/272832.html
標籤:其他
上一篇:2021數字中國創新大賽虎符網路安全賽-部分Writeup
下一篇:sqli-labs通關筆記
