1. 程式人生 > >C++11--移動建構函式

C++11--移動建構函式

【知識點梳理】

1、預設建構函式為淺拷貝

2、左值和右值

3、右值引用優化效能,避免深拷貝

4、移動建構函式

【正文】

class A_2
{
public:
	A_2() :m_ptr(new int(0))
	{

	}

	~A_2()
	{
		delete m_ptr;
	}

private:
	int* m_ptr;
};

A_2 Get(bool flag)
{
	A_2 a;
	A_2 b;
	if (flag)
		return a;
	else
		return b;
}

int right_value_ref2()
{
	A_2 a = Get(false);  //執行報錯

	return 0;
}

在上面的程式碼中,預設建構函式是淺拷貝,a和b會指向同一指標m_ptr,在解構函式會導致重複刪除該指標。

正確的做法是提供深拷貝的拷貝建構函式。

A_2(const A_2& a):m_ptr(new int(*a.m_ptr)) //深拷貝
{
	std::cout << "copy construct" << std::endl;
}

這樣就可以保證拷貝構造時的安全性,但有時這種拷貝構造卻是不必要的,不人上面程式碼中的拷貝構造就是不必要的。上面程式碼中的Get函式會返回臨時變數,然後通過這個臨時變數拷貝構造一個新的物件b,臨時變數在拷貝構造完成之後就銷燬了,如果堆記憶體很大,那麼,這個拷貝構造的代價會很大,帶來了額外的效能損耗。

有沒有辦法避免臨時物件的拷貝構造呢?答案是肯定的。看下面的程式碼:

class A_2
{
public:
	A_2() :m_ptr(new int(0))
	{
		std::cout << "construct" << std::endl;
	}

	A_2(const A_2& a):m_ptr(new int(*a.m_ptr)) //深拷貝
	{
		std::cout << "copy construct" << std::endl;
	}

	A_2(A_2&& a) :m_ptr(a.m_ptr)
	{
		a.m_ptr = nullptr;
		std::cout << "move construct:" << std::endl;
	}

	~A_2()
	{
		std::cout << "destruct" << std::endl;
		delete m_ptr;
	}

private:
	int* m_ptr;
};

A_2 Get(bool flag)
{
	A_2 a;
	A_2 b;
	if (flag)
		return a;
	else
		return b;
}

int right_value_ref2()
{
	A_2 a = Get(false);

	return 0;
}

    上面的程式碼中沒有了拷貝構造,取而代之的是移動構造(Move Construct)。從移動建構函式的實現可以看到,它的引數是一個右值引用型別的引數A&&,這裡沒有深拷貝,只有淺拷貝,這樣就避免了臨時物件的深拷貝,提供了效能。這裡的A&&用來根據引數是左值還是右值來建立分支,如果是臨時值,則會選擇移動建構函式。移動建構函式只是將臨時物件的資源做了淺拷貝,不需要對其進行深拷貝,從而避免了額外的拷貝,提高效能。這也就是所謂的移動語義(move 語義),右值引用的一個重要目的是用來支援移動語義的。

       移動語義可以將資源(堆、系統物件等)通過淺拷貝方式從一個物件轉移到另一個物件,這樣能減少不必要的臨時物件的建立、拷貝以及銷燬,可以大幅度提高C++應用程式的效能,消除臨時物件的維護(建立和銷燬)對效能的影響。

相關推薦

C++11 移動建構函式

文章目錄 一、引言 二、左值和右值 三、深拷貝建構函式 四、右值引用 五、移動建構函式 六、std::move() 七、參考資料 一、引言 移動建構函式是什麼?先舉個例子,你有一本書,你不想看,但我很想看,那麼我

C++11--移動建構函式

【知識點梳理】1、預設建構函式為淺拷貝2、左值和右值3、右值引用優化效能,避免深拷貝4、移動建構函式【正文】class A_2 { public: A_2() :m_ptr(new int(0)) { } ~A_2() { delete m_ptr; }

c++11 繼承建構函式

若基類擁有數量眾多的不同版本的建構函式,而派生類中只有一些成員函式,則對於派生類而言,其建構函式就等同於構造基類。 struct A { A(int i) {} A(double d, int i) {} A(float f, int i, const char* c) {} //... };

c++11:物件移動 & 右值引用 & 移動建構函式

一、概述 c++ 11 新標準中最主要的特徵是可以移動而非拷貝物件的能力。很多情況下,物件拷貝後就會立即被銷燬。 在這些情況下,移動而非拷貝物件會大幅度提升效能。 在舊 C++ 標準中,沒有直接的方法移動物件。因此,即使不必要拷貝物件的情況下,我們也不得不拷貝。如果物件本身要求

C++11學習9---移動建構函式

主要講的是如何實現移動構造。 1.移動構造的原因 這個移動構造,或者移動拷貝賦值,有竊取資源的意思。 這個竊取資源時對於指標持有的資源來說的。 而這個竊取是通過在建構函式與過載拷貝賦值的時候,編碼將當前的指標指向資源,再將原來的指標,指向nullptr實現的。 當然,你也可

C++11特性--新的類功能--特殊的成員函式(移動建構函式移動賦值運算子),預設方法和禁用方法(default,delete),委託建構函式,管理虛方法(override,final)

      class A      {         public:            void fun(int x )            {               cout<<x<<endl;             }                      

C++11新特性(51)- 移動建構函式通常應該是noexcept

不會丟擲異常的移動建構函式 拷貝建構函式通常伴隨著記憶體分配操作,因此很可能會丟擲異常;移動建構函式一般是移動記憶體的所有權,所以一般不會丟擲異常。 C++11中新引入了一個noexcept關鍵字,用來向程式設計師,編譯器來表明這種情況。 noexc

C++11中std::move、std::forward、左右值引用、移動建構函式的測試

關於C++11新特性之std::move、std::forward、左右值引用網上資料已經很多了,我主要針對測試效能做一個測試,梳理一下這些邏輯,首先,左值比較熟悉,右值就是臨時變數,意味著使用一次就不會再被使用了。針對這兩種值引入了左值引用和右值引用,以及引用摺疊的概念。 1.右值引用的舉例測試 #in

C++複製建構函式&移動建構函式,複製賦值運算子&移動賦值運算子

一、呼叫時機 1、複製建構函式呼叫的時機 ·物件在建立時使用其他的物件初始化 Person p(q); //此時複製建構函式被用來建立例項p Person p = q; //此時複製建構函式被用來在定義例項p時初始化p return_p()  //當函式返回該型別的物件

C++類的特殊成員-預設/拷貝/移動建構函式

首先學習這章,需要對動態記憶體分配有一定的理解。 類的特殊成員函式有六個,如下: 接下來讓我們逐一分析: 1 預設建構函式 預設建構函式相信大家都不陌生了,只有當沒有宣告建構函式或者物件在宣告的時候沒有任何初始化引數就會呼叫預設建構函式。 cl

c++11 移動語義

應用程序 color 值引用 移動語義 delete system fine blog 相對 c++11 移動語義 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <stri

43.StrVec類:std::move呼叫移動建構函式的一個例項

自定義一個strvec類,在記憶體不夠,開闢新的記憶體存放元素的時候(也即是reallocate),使用移動操作!而非拷貝! using namespace std; class strvec { private: static allocator<string>alloc;

42.移動建構函式的合成規則

不會使用移動造作: 當類的類成員定義了自己的拷貝建構函式且未定義移動建構函式 當類的類成員沒有定義自己的拷貝建構函式且編譯器不能為其合成移動建構函式 當有類的成員的移動建構函式或者移動賦值運算子是刪除的或者不可訪問的 當類的成員存在成員引用或者const的時候,移動賦值運算子被定

JNI之 c/c++呼叫java建構函式

有時候c/c++是面向過程編碼,很多有用工具類都沒有,要編碼人員自己實現,如果可以呼叫java大量存在的類豈不是更省事更簡潔。 下面是通過呼叫java的Date類產生是時間戳。 public class JniConsTest { //c訪問java建構函式,並返回物件

C++類中建構函式

我們在定義一個類之後,在利用該類定義了一個物件後,往往需要對該物件中資料成員變數進行初始化。有時候我們會誤操作,忘記初始化或者重複初始化,這樣做都會造成程式的崩潰。C++給我們提供了一個很有用的方法,就是類的建構函式。 C++類的建構函式,和其它成員函式一樣,在類中定義。不過建構函式和其他成

C++】拷貝建構函式

目錄 拷貝建構函式 拷貝建構函式的呼叫 預設的拷貝建構函式 深度拷貝  看完類的建構函式後,再來了解下拷貝建構函式。 拷貝建構函式 拷貝建構函式是一種特殊的建構函式。 (1)它是建構函式,所以函式名就是類名,沒有返回值; (2)它是特殊的建構函式,引

c++合成預設建構函式

轉自:點選開啟連結 對於C++預設建構函式,我曾經有兩點 誤解 : 類如果沒有定義任何的建構函式,那麼編譯器(一定會!)將為類定義一個合成的預設建構函式。 合成預設建構函式會初始化類中所有的資料成員。 第一個誤解來自於我學習C++的第一本書 《C++

C++學習筆記——建構函式例項

/************************************************************************************************************************************************ 1.&n

C++學習筆記——建構函式(二)

委託建構函式:使用類的其他建構函式執行初始化過程 Clock(int newH, int newM, int newS): hour(newH), minute(newM), second(newS){ } Clock:Clock(0,0,0){} //無參建構函式呼叫有參建構函式,將預設初始化

C++學習筆記——建構函式(一)

建構函式: 類中的特殊函式 用於描述初始化演算法 在物件被建立時使用特定的值構造物件,將物件初始化為一個特定的初始狀態 建構函式的形式: 函式名必須與類名相同 不能定義返回值型別,也不能有return語句 可以有形參,也可以沒有 可以時行內函