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...