移動建構函式

2021-08-13 01:29:43 字數 2816 閱讀 9092

移動構造:

移動構造是c++11標準中提供的一種新的構造方法。

在現實中有很多這樣的例子,我們將錢從乙個賬號轉移到另乙個賬號,將手機

sim卡轉移到另一台手機,將檔案從乙個位置剪下到另乙個位置……

移動構造可以減少不必要的複製,帶來效能上的提公升。

有些複製構造是必要的,我們確實需要另外乙個副本;而有些複製構造是不必要的,我們可能只是希望這個物件換個地方,移動一下而已。

在c++11之前,如果要將源物件的狀態轉移到目標物件只能通過複製。

而現在在某些情況下,我們沒有必要複製物件——只需要移動它們。

c++11引入移動語義:

~源物件資源的控制權全部交給目標物件

對比一下複製構造和移動構造:

複製構造是這樣的:

在物件被複製後臨時物件和複製構造的物件各自占有不同的同樣大小的堆記憶體,就是乙個副本。

移動構造是這樣的:

就是讓這個臨時物件它原本控制的記憶體的空間轉移給構造出來的物件,這樣就相當於把它移動過去了。

複製構造和移動構造的差別:

這種情況下,我們覺得這個臨時物件完成了複製構造後,就不需要它了,我們就沒有必要去首先產生乙個副本,然後析構這個臨時物件,這樣費兩遍事,又占用記憶體空間,所幸將臨時物件它的原本的資源直接轉給構造的物件即可了。

當臨時物件在被複製後,就不再被利用了。我們完全可以把臨時物件的資源直接移動,這樣就避免了多餘的複製構造。

什麼時候該觸發移動構造呢?

如果臨時物件即將消亡,並且它裡面的資源是需要被再利用的,這個時候我們就可以觸發移動構造。

移動構造是需要通過移動建構函式來完成的。

移動建構函式定義形式:

class_name(class_name && )

例:函式返回含有指標成員的物件

有兩種版本:

版本一:使用深層複製建構函式

~ 返回時構造臨時物件,動態分配臨時物件返回到主調函式,然後刪除臨時物件。

版本二:使用移動建構函式

~ 將要返回的區域性物件轉移到主調函式,省去了構造和刪除臨時物件的過過程。

版本一舉例:使用複製構造的**:

[cpp]

view plain

copy

#include

using

namespace

std;    

class

intnum    

intnum(const

intnum &n):xptr(

newint

(*n.xpr))    

~intnum()    

intgetint()

//返回指標所指向的值,而不是返回指標本身  

private

:    

int*ptr;    

};    

//返回值為intnum類物件  

intnum getnum()    

intmain()    

版本一通過深層複製建構函式實現的返回含有指標成員的物件,在這個過程中,做了一些無用功,既需要構造臨時無名(注:是無名物件,不是上例中的物件a)物件,還要對其進行析構。

在上例中不構造臨時無名物件不行嗎?其實呢我們也不用構造臨時無名物件了,物件a

反正是要消亡的,我們把要消亡的物件a占用的資源轉移給臨時物件,不行嗎?!這樣的方案就是使用移動構造

版本二:使用移動構造

使用移動建構函式的**舉例:

[cpp]

view plain

copy

#include

using

namespace

std;    

class

intnum    

intnum(const

intnum &n):xptr(

newint

(*n.xpr))   

intnum(intnum && n):xptr(n.xptr)  

~intnum()   

intgetint()

//返回指標所指向的值,而不是返回指標本身  

private

:    

int*ptr;    

};    

//返回值為intnum類物件  

intnum getnum()    

intmain()    

在該例中的移動建構函式

intnum(intnum && n):xptr(n.xptr){//移動建構函式

n.xptr = nullptr;

cout<

看函式體裡面,我們發現再做完xptr(n.xptr)這種指針對指標的複製(也就是把引數指標所指向的物件轉給了當前正在被構造的指標)後,接著就把引數n裡面的指標置為空指標(n.xptr = nullptr;),物件裡面的指標置為空指標後,將來析構函式析構該指標(delete xpr;)時,是delete乙個空指標,不發生任何事情,這就是乙個移動建構函式。

移動建構函式中的引數型別,&&符號表示是右值引用;即將消亡的值就是右值,函式返回的臨時變數也是右值,這樣的單個的這樣的引用可以繫結到左值的,而這個引用它可以繫結到即將消亡的物件,繫結到右值

左值和右值都是針對表示式而言的,左值是指表示式結束後依然存在的持久物件,右值指表示式結束時就不再存在的臨時物件——顯然右值不可以被取位址。

關於左值、右值和右值引用的詳細內容可以參考:

移動建構函式

c 11新引入了右值引用和移動語義兩個概念。c 包括c 中所有的表示式和變數要麼是左值,要麼是右值。通俗的左值的定義就是非臨時物件,可以在多條語句中使用的物件。右值是指臨時的物件,它們只在當前的語句有效。在c 11之前,右值是不能被引用的。如int a 1 無法從 int 轉化為 int 我們最多只...

剖析 移動建構函式

移動建構函式應用的場景?答 有時候我們會遇到這樣一種情況,我們用物件a初始化物件b,後物件a我們就不在使用了,但是物件a的空間還在呀 在析構之前 既然拷貝建構函式,實際上就是把a物件的內容複製乙份到b中,那麼為什麼我們不能直接使用a的空間呢?這樣就避免了新的空間的分配,大大降低了構造的成本。這就是移...

拷貝建構函式和移動建構函式解析

by gongzhihui 2017.12.5 拷貝構造函式呼叫時機 1.物件作為函式引數 2.物件作為函式返回值 3.用乙個物件初始化另乙個物件 t t1 t t2 ti t t3 t1 此處的 不是賦值運算子 拷貝賦值運算子 t t1 t t2 t1 t2 除了 類名 物件 物件 外的 應該都是...