拷贝构造函数
拷贝构造函数是一种特殊的构造函数,它在创建对象时,使用的是同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:
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 constructor CExample(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 一个对象需要通过另外一个对象进行初始化