學習記錄(2)拷貝控制

2021-07-31 20:34:58 字數 3459 閱讀 7602

拷貝控制操作包括:拷貝建構函式、拷貝賦值運算子、移動建構函式、移動賦值運算子和析構函式。

class foo;
這裡有個簡單的規則:如果你需要定義乙個非空的析構函式,那麼,通常情況下你也需要定義乙個拷貝建構函式。

拷貝初始化發生在以下情況:

(1)用「=」定義變數

(2)將乙個物件作為實參傳遞給乙個非引用型別的形參。

(3)從乙個返回型別為非引用型別的函式返回乙個物件。

(4)用{}列表初始化乙個陣列中的元素或乙個聚合類中的成員。

補充:編譯系統在我們沒有自己定義拷貝建構函式時,會在拷貝物件時呼叫預設拷貝建構函式,進行的是淺拷貝

#include 

using

namespace

std;

class student

;student::student()

student::~student()

int main()

上述程式中,由於系統呼叫的是預設拷貝建構函式,沒有重新分配記憶體,兩個指標指向同一塊記憶體,而析構函式呼叫了兩次,引起記憶體洩露。

所以在對含有指標成員的物件進行拷貝時,必須要自己定義拷貝建構函式,使拷貝後的物件指標成員有自己的記憶體空間,即進行深拷貝,這樣就避免了記憶體洩漏發生。

#include 

using

namespace

std;

class student

;student::student()

student::student(const student &s)

student::~student()

int main()

class foo;

合成拷貝賦值運算子:

sales_data& sales_data::operator=(const sales_data &rhs)

不能被過載。成員按初始化順序的逆序銷毀。

無論何時乙個物件被銷毀,就會自動呼叫其析構函式:

4.三五法則

可以控制類的拷貝操作:拷貝建構函式、拷貝賦值運算子和析構函式。

如果乙個類需要自定義析構函式,幾乎肯定它也需要自定義拷貝賦值運算子和建構函式。)

如果乙個類需要自定義拷貝建構函式,幾乎可以肯定它也需要乙個拷貝賦值運算子

5.使用=default

在類中用=default修飾成員的宣告,合成的函式將隱式地宣告成內聯的,並且只能對合成版本的成員函式使用。

6.阻止拷貝

定義刪除的函式 =delete 雖然進行了宣告,但不能以任何方式使用。=delete必須出現在第一次宣告的時候。注:析構函式不能是刪除的成員

c++11發布前是通過private來阻止拷貝

class privatecopy
管理類外資源的類必須定義拷貝控制成員。

1.行為像指標的類

class hasptr

//對ps指向的string 每個hasptr都有自己的拷貝

hasptr(const hasptr &p):ps(new

string(*p.ps)),i(p.i){}

hasptr& operator=(const hasptr &);

//釋放ps

~hasptr()

private:

string *ps;

int i;

}

hasptr::operatpr = (const hasptr& has)
2.定義行為像指標的類

引用計數的工作方式如下:

class

hasptr

//拷貝建構函式拷貝所有三個成員,並遞增計數器

hasptr(const hasptr& has) : ps(has.ps), i(has.i), use(has.use)

hasptr& operator = (const hasptr& has);

~hasptr();

private:

string* ps;

int i;

size_t* use; // 計數

};

hasptr::hasptr& operator = (const hasptr& has)

ps = has.ps;

i = has.i;

use = has.use;

return *this;

} hasptr::~hasptr()

}

管理類外資源的類通常還定義了名為swap的函式。

class

hasptr

inline void swap(hasptr &lhs ,hasptr &rhs)

在賦值運算子中使用swap,拷貝並交換技術。

//異常安全的,且能正確處理自賦值

hasptr& hasptr::operator=(hasptr rhs)

類似於對應的拷貝操作,但它們從給定物件「竊取」資源而不是拷貝資源

//類似於拷貝建構函式,但注意這裡的引用引數是乙個右值引用

//通常不分配任何資源,因此移動通常不會丟擲異常,所以加上noexcept

strvec::strvec(strvec &&s)noexcept

:elements(s.elements),first_free(s.first_free),cap(s.cap)

不丟擲異常的移動建構函式和移動賦值運算子必須標記為noexcept

strvec::strvec operator=(strvec &&rhs) noexcept

return *this;

}

只有當乙個類沒有定義任何自己版本的拷貝控制成員,且類的每個非static資料成員都可以移動時,編譯器才會為它合成移動建構函式或移動賦值運算子。

struct x;

struct hasx

x x,x2=move(x);//使用合成的移動建構函式

hasx hx,hx2=move(x);//使用合成的移動建構函式

學習記錄 js深拷貝 淺拷貝

js 的資料型別有兩種,一種是基本資料型別 string number boolean null undefined symbol 一種是引用資料型別 object array function 基本資料型別是放在棧記憶體的,而引用資料型別是存放在堆記憶體的,它會在棧記憶體裡面存放乙個指向堆記憶體的...

C primer學習 拷貝控制 1

1 我們使用 定義變數 2 從乙個返回型別為非引用的函式返回物件 3 用花括號列表初始化乙個陣列中的元素或者乙個聚合類的成員.4 某些類型別對它們所分配的物件使用拷貝初始化.point global point foo bar point arg 第1處 第4,5初 return heap 第6處 ...

C primer學習 拷貝控制 3

strblob const strblob rhs 拷貝初始化 strblob operator const strblob rhs 練習 定義乙個使用引用計數的hasptr類class hasptr 在拷貝建構函式中定義三個成員,並且初始化引用計數為1 hasptr const hasptr h ...