拷貝建構函式(C 學習筆記 25)

2021-09-01 05:41:57 字數 3572 閱讀 6900

point p2

(p1)

;

其作用是,在建立新物件p2時,用已經存在的物件p1去初始化新物件p2,在這個過程中就要呼叫拷貝建構函式。

自定義拷貝建構函式(見例 1)

類名::類名(const 類名 &物件名)

普通的建構函式是在物件建立時被呼叫,而拷貝建構函式在以下3中情況下都會被呼叫:

1、當用類的乙個物件去初始化該類的另乙個物件時。

有 代入法 和 賦值法 兩種方法呼叫拷貝建構函式。

代入法:

類名 物件2(物件1)

例如:point p1(p2);

賦值法:

類名 物件2=物件1;

例如:point p2=p1;

在這裡要注意 「 賦值法呼叫拷貝建構函式 」 和 「 物件賦值語句 」 的區別,物件賦值語句不會呼叫拷貝建構函式,它是通過預設運算子函式實現的。

這裡的物件賦值是指對其中的資料成員賦值,而不對成員函式賦值。

2、當函式的形參是類的物件,在呼叫函式進行形參和實參結合時。

例如:

void

fun1

(point p)

//形參是類point的物件

intmain()

如果類point中有自定義的拷貝建構函式,就呼叫這個自定義的拷貝建構函式,否則就呼叫系統自動生成的預設拷貝建構函式。

3、當函式的返回值是類的物件,在函式呼叫完畢將返回值(物件)帶回函式呼叫處時,此時就會呼叫拷貝建構函式,將此物件複製給乙個臨時物件並傳到該函式的呼叫處。

例如:

point fun2()

//函式fun2的返回值型別是point類型別

intmain()

在上例中,物件p1是在函式fun2中定義的,在呼叫函式fun2結束時,p1的生命週期結束了,因此在函式fun2結束前,執行語句「return p1;」時,將會呼叫拷貝建構函式將p1的值複製到乙個臨時物件中,這個臨時物件時編譯系統在主程式中臨時建立的。函式執行結束時,物件p1消失,但臨時物件將會通過語句「p2=fun2( )」將它的值賦給物件p2。執行完成這個語句後,臨時物件的使命也就完成了,該臨時物件便自動消失了。

例 1:自定義拷貝建構函式的使用。

#include

using

namespace std;

class

point

point

(const point &p)

void

print()

private

:int x,y;};

intmain()

例 2:呼叫拷貝建構函式的3種情況。
#include

using

namespace std;

class

point

;point::

point

(int a,

int b)

point::

point

(const point &p)

void point::

print()

void

fun1

(point p)

point fun2()

intmain()

執行結果:

按說,第三種情況的應該也會呼叫拷貝建構函式,但是顯示的結果卻意味著沒有呼叫。這是由於rvo優化。

rvo優化:

return value optimistic,指當乙個函式返回乙個值型別而非引用型別時,可以繞過拷貝/移動建構函式,直接在呼叫函式的地方構造返回值。

那怎麼去除rvo優化呢?

參考文章:

可以看到正確的執行結果了!!!

例 3:拷貝建構函式練習-1

#include

using

namespace std;

class

point3d

~point3d()

point3d

(const point3d &other)

point3d &

operator=(

const point3d &other)

cout <<

"operator="

<

return

*this;}

};point3d factory()

intmain()

執行結果:

例 4 :拷貝建構函式練習-2

**來自:

#include

using

namespace std;

classaa

(const string &d)

:str

(d)

string str;};

void

func

(a a)

intmain()

首先呼叫std::string 的建構函式,通過乙個字串常量,構造了乙個std::string物件,這個物件是個臨時值,也就是說是個右值,我們叫它為string_temp。

在函式呼叫過程中,具有非引用型別的引數要進行拷貝初始化。這裡只能通過const string &的建構函式先構造出乙個臨時a型別物件,再用該物件執行拷貝初始化。

string_temp和a型別並不相等,這裡進行了隱式轉換,單引數的隱式轉換static_cast(string_temp)等同於a(string_temp),根據string_temp的型別決議使用const std::string &型別的建構函式。

然後由於func的引數是乙個a型別的物件,並且a有乙個引數為const string &的建構函式,並且它沒有explicit修飾,也就支援通過std::string隱式轉換為a。那麼在這裡,便通過string_temp構造出了乙個a型別物件,同樣是臨時值(右值),我們叫它a_temp。

但是因為func的引數是乙個a型別的物件,並不是乙個引用,所以應該呼叫拷貝建構函式將a_temp拷貝到a。

這裡發生了1次string的構造(string_temp),1次a的構造(a_temp),1次a的拷貝構造(a)。

C 學習筆記 拷貝建構函式

拷貝建構函式是一種特殊的建構函式 1 它是建構函式,所以函式名是類名 沒有返回值 2 它是特殊的建構函式 引數形式是固定的 class object 拷貝建構函式的含義 以乙個物件為藍本,來構造另乙個物件。object b object a b 稱作 以b為藍本,建立乙個新的物件a。a是b的乙個拷貝...

C 學習筆記 C 拷貝建構函式(5)

拷貝建構函式是一種特殊的建構函式,它在建立物件時,是使用同一類中之前建立的物件來初始化新建立的物件。拷貝建構函式通常用於 通過使用另乙個同型別的物件來初始化新建立的物件。複製物件把它作為引數傳遞給函式。複製物件,並從函式返回這個物件。如果類帶有指標變數,並有動態記憶體分配,則它必須有乙個拷貝建構函式...

C 學習筆記之建構函式(三)拷貝(複製)建構函式

定義 使用類的乙個物件來構造和初始化另乙個物件,這另乙個物件之前是不存在的。要注意理解拷貝 複製 和賦值的區別,拷貝和複製時另乙個物件之前是不存在的,而賦值是兩個物件都構造好了。如 a a a b a a b a 這是拷貝 a a a b b a 這是賦值 拷貝建構函式的過載宣告如下 a const...