C 11新特性學習筆記之移動建構函式

2021-07-25 07:35:15 字數 2060 閱讀 2766

一般來說,如果乙個類中有指標成員,則要小心拷貝成員函式的編寫,因為如果不注意,則會造成程式的記憶體洩漏。如下所示的例子。

#include 

class hasptrmem

~hasptrmem()

}int *m_data;

};int main()

我們申明了乙個帶有指標成員的hasptrmem類,在main函式中宣告了物件a,再用物件a去初始化b,由於類中沒有顯示宣告拷貝建構函式,則按照c++語法會呼叫編譯器隱式生成的拷貝建構函式。這樣就會出現以下乙個問題:

a和b的m_data和都指向同一塊堆記憶體,因此在main作用域結束後,a和b的析構函式依次被呼叫,比如b.m_data所指向的記憶體先被釋放後,a.m_data就無法再對其進行操作,從而導致記憶體洩漏。

上述拷貝構造方式就是淺拷貝(shallow copy):只對資料成員進行簡單的賦值。

深拷貝(deep copy):針對存在指標資料成員的情況下,重新分配記憶體空間,不再是簡單的指標賦值。如下所示。

#include 

class hasptrmem

hasptrmem(hasptrmem& h) : m_data(new

int(*h.m_data)){} //拷貝建構函式,從堆中分配記憶體,用h.m_data初始化

~hasptrmem()

}int *m_data;

};int main() //正常析構

執行結果: 0 0

上述結果就不會報錯,新的拷貝建構函式從堆中分配心記憶體,將分配來的記憶體的指標交給m._data,通過這樣的方法,就能避免產生懸掛指標(dangling pointer)。

如果指標所指向非常大的記憶體資料的話,則拷貝構造的代價就非常昂貴,會極大地影響效能。c++11提供一種簡潔解決方法:移動建構函式,即是在用原物件指針對新物件指標進行賦值後,將原物件成員指標置為空指標,使得其無法指向記憶體資料,從而保證在析構的時候不會產生記憶體洩漏。這樣既不用分配新記憶體,也不會產生記憶體洩漏,從而很好地解決了上述問題。如下所示。

#include 

class hasptrmem

hasptrmem(const hasptrmem &h) : m_data(new

int(*h.m_data))

hasptrmem(hasptrmem&& h) :m_data(h.m_data)

~hasptrmem()

std::cout

<< "destruct: "

<< ++n_dstr << std::endl;

}int *m_data;

static

int n_cstr;

static

int n_dstr;

static

int n_cptr;

static

int n_mvtr;

};int hasptrmem::n_cstr = 0;

int hasptrmem::n_cptr = 0;

int hasptrmem::n_mvtr = 0;

int hasptrmem::n_dstr = 0;

hasptrmem gettemp()

int main()

執行結果:

construct: 1

resource from gettemp:000000e2e9b55d00

move construct: 1

destruct: 1

resource from main:000000e2e9b55d00

destruct: 2

gettemp()函式返回了h的乙個臨時變數時,呼叫了移動建構函式,其中的h和main中的a的指標成員值是相同的,說明了h.m _data和a.m _data都指向了相同的堆記憶體位址.因此其指標在gettemp函式返回時免於被析構的「命運」,成為main中a的變數。

移動建構函式能解決佔記憶體較大的物件的拷貝構造問題,對提高系統效能有很好的作用。

C 11新特性 移動建構函式和移動賦值

移動建構函式就是從拷貝建構函式演化而來的。拷貝建構函式又分為淺拷貝和深拷貝 因此就產生了移動建構函式,將原來物件的東西移動到新的物件上 移動後當物件銷毀時不能發生錯誤 移動後原物件不再指向被移動的資源,這些資源的所有權已經歸屬新建立的物件 a a x a a x 上面兩種就是拷貝建構函式和移動建構函...

C 11新特性學習

lambda表示式用於建立匿名的函式物件,語法為 函式可訪問的的外部變數 函式引數 返回值型別 如 int a 1,b 2 int c b int x int b 表示函式中可以訪問外部變數b,而且引數b是按值傳遞,b 表示引數b是按引用傳遞,表示可以訪問所有外部變數,並且是用按值傳遞方式,類似,也...

C 11新特性學習筆記(二)

c 11引入了lambda 匿名函式 這樣就可以在乙個函式只需呼叫一次的地方使用了,類似內聯函式。c 11 的 lambda 表示式規範如下 capture params mutable exception attribute ret 1 capture params ret 2 capture p...