拷貝構造函數是一種特殊的構造函數,它在創建對象時,使用的是同一類中之前創建的對象來初始化新創建的對象。拷貝構造函數通常用于:
l? 通過使用另一個同類型的對象來初始化新創建的對象;
l? 復制對象把它作為參數傳遞給函數;
l? 復制對象,并從函數返回這個對象。
?
如果類中沒有定義拷貝構造函數,編譯器會自行定義一個。如果類中帶有指針變量,并有動態內存分配,則它必須有一個拷貝構造函數。拷貝構造函數最常見的形式如下:
classname(const classname &obj) {//構造函數主體 }
在這里,obj是一個對象的引用,該對象是用于初始化另一個對象的。
/*** copy_constructor.cpp ***/ #include<iostream> using namespace std;class Line {public:Line(int len);Line(const Line & obj);~Line(); int getLength(void);private:int *ptr; };Line::Line(int len) {cout << "call construct func" << endl;//allocate memory for pointer ptr = new int;*ptr = len; }Line::Line(const Line &obj) {cout << "call copy constructor func and allocate memory for point" << endl;ptr = new int;*ptr = *obj.ptr; }Line::~Line(void) {cout << "free memory" << endl;delete ptr; }int Line::getLength(void) {return *ptr; }void display(Line obj) {cout << "the size of line : " << obj.getLength() << endl; }int main() {Line line(10);display(line);return 0; }
運行結果:
exbot@ubuntu:~/wangqinghe/C++/20190806$ ./copy
call construct func
call copy constructor func and allocate memory for point
the size of line : 10
free memory
free memory
?
void display(Line obj) //通過gdb調試,該程序在 Line obj處進入拷貝函數構造。
?
如果使用以下的main
int main() {Line line1(10);Line line2 = line1;display(line1);display(line2);return 0; }
運行結果:
exbot@ubuntu:~/wangqinghe/C++/20190806$ ./copy
call construct func
call copy constructor func and allocate memory for point
call copy constructor func and allocate memory for point
the size of line : 10
free memory
call copy constructor func and allocate memory for point
the size of line : 10
free memory
free memory
free memory
?
在C++中,對象以值傳遞的方式傳入函數參數:
/*** value_transf.cpp ***/ #include<iostream> using namespace std;class CExample {public:CExample(int b){a = b;cout << "create: " << a << endl;}//copy constructorCExample(const CExample& C){a = C.a;cout << "copy constructor" << endl;}//destructor~CExample(){cout << "delete: " << a << endl;}void show(){cout << a << endl;}private:int a; };void g_Fun(CExample C) {cout << "test" << endl; }int main() {CExample test(1);g_Fun(test);return 0; }
運行結果:
exbot@ubuntu:~/wangqinghe/C++/20190806$ g++ value_transf.cpp -o value_transf -g
exbot@ubuntu:~/wangqinghe/C++/20190806$ ./value_transf
create: 1
copy constructor
test
delete: 1
delete: 1
調用g_Fun()時,會產生以下幾個重要的步驟:
1) test對象傳入形參時,會先產生一個臨時變量,暫且稱呼C
2) 然后調用拷貝構造函數把test值給C。這兩個步驟很像:CExample C
3) 等g_Fun()執行完后,析構掉C對象。
?
拷貝構造函數是一種特殊的構造函數,具有單個形參,該形參(常用const修飾)是對該類類型的引用。當定義一個新對象并用一個同類型的對象把它進行初始化時,將顯示使用拷貝構造函數或從函數返回該類型的對象時,將隱式調用拷貝構造函數。
?
C++支持兩種初始化形式:
拷貝初始化:int a = 5;和直接初始化 int a(5);
對于其他類型沒有什么區別,對于類類型直接初始化直接調用實參匹配的構造函數,拷貝構造初始化總是調用拷貝構造函數,也就是說
A x(2);? //直接初始化,調用構造函數
A y = x; //拷貝初始化,調用拷貝構造函數。
必須定義拷貝構造函數的情況:
只包含類類型成員或內置類型(但不是指針類型)成員的類,無須顯示地定義拷貝構造函數也可以拷貝;有的類有一個數據成員是指針,或者是由成員表示在構造函數中分配的其他資源,這兩種情況下都必須定義拷貝構造函數。
?
以下情況使用拷貝構造函數:
類的對象需要拷貝時,拷貝構造函數將會調用。以下情況都會調用拷貝構造函數:
l? 一個對象以值傳遞的方式進入函數體
l? 一個對象以值傳遞的方式從函數返回
l? 一個對象需要通過另外一個對象進行初始化
?