C++拷贝构造函数详解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

/blog/static/11 22252200691732259479/

拷贝构造函数问题集锦

2006-10-18 16:48:10| 分类:C/C++ | 标签:c/c++ 体验 it linux |字号订阅

一、什么是拷贝构造函数

用一个类的一个对象去构造另一个对象,或者说初始化一个新构造的对象时。往往会通过拷贝构造函数。假设存在一个类A,那么声明A的拷贝构造函数如下:

A (A &a);

可见,它与一般的构造函数在于,他的参数是本类对象的一个引用。

二、什么情况会调用构造函数

从构造函数的定义来看,当用一个对象去初始化或构造一个对象时,就会调用构造函数。在程序的运行过程中,这个初始化或构造的过程可能是隐式的,也可能是显式的。显式的只有一种情况,如下面调用(假想存在对象obj)

A(obj);

另外还有一些隐式调用的情况。为了说明方便,我们首先写如下类。

#include

#include

using namespace std;

class CopyTest

{

public:

int i;

CopyTest()

{

cout << "调用默认构造函数!" <

i = 3;

}

//COPY构造函数

CopyTest( CopyTest &obj)

{

cout << "调用拷贝构造函数!"<

i = 10;

}

CopyTest operator = (CopyTest &obj)

{

cout <<"调用赋指重载!"<

this->i = obj.i;

}

};

类中有一个默认构造函数的重载,COPY构造函数的重载,和一个赋值运算符的重载,我们通过几个调用来说明何时会调用COPY构造函数。

1.定义对象-- 调用指定的构造函数

int main(int argc, char *argv[])

{

CopyTest obj1;

getchar();

return EXIT_SUCCESS;

}

在上例中,调用默认的构造函数。如果在定义对象的同时写上其它的参数。运行过程中会调用相应的参数。

2、初始化一个对象

初始化指定义一个对象同时给他同值。如下面这种写法

CopyTest obj2 = obj1;

但是,如果把上述语句改为

CopyTest obj2 ;

obj2= obj1;

运行时并没有调用COPY构造函数。原因是,上述过程只是赋值,而不是一个初始化的过程。事实上,系统默认已经对obj2进行了初始化。

3、形参实体化

看下面一个例子:

int Test(CopyTest obj)

{

return 1;

}

int main(int argc, char *argv[])

{

CopyTest obj1;

Test(obj1);

getchar();

return EXIT_SUCCESS;

}

在这个过程中调用的拷贝构造函数。我们可以把这个过程理解为CopyTest obj = obj1;显然这是一个初始化的过程。所以,理所当然的调用的拷贝构造函数。

值得指出的是,当传递的参数是引用或指针时,不会调用该类的构造函数。原因是,这个过程,只是对引用和指针的复制。而不是对对角本身的复制,没有产生新的对象,形参和实参所指代的是一个对象。当然这个过程不会调用拷贝构造函数了。

4、返回一个对象

当某个函数,以一个对象作为返回值时,会调用拷贝构造函数。事实上,当函数返回时,会创建一个临时变量,并对其进行初始化,把所要返回的对象赋给临时变量。所以这个过程是要调用拷贝构造函数的。

三、何时重载拷贝构造函数

C++规定,每一个类都有一个默认的无参构造函数和一个默认的拷贝构造函数。一般情况下,我们运用这两个默认的构造函数就可以完成上述的工作。但有一些情况是例外。

例如:类体内的成员是需要开辟动态开辟堆内存的,如果我们不自定义拷贝构造函数而让系统自己处理,那么就会导致堆内存的所属权产生混乱,试想一下,已经开辟的一端堆地址原来是属于对象a的,由于复制过程发生,b对象取得是a已经开辟的堆地址,一旦程序产生析构,释放堆的时候,计算机是不可能清楚这段地址是真正属于谁的,当连续发生两次析构的时候就出现了运行错误。

上例是一个很明显的深拷贝问题。所谓深拷贝与浅拷贝可以如下理解:如果一个类拥有资源(堆,或者是其它系统资源),当这个类的对象发生复制过程的时候,这个过程就可以叫做深拷贝,反之对象存在资源但复制过程并未复制资源的情况视为浅拷贝。(摘自太平洋电脑网)

往往在深拷贝中,我们要重载拷贝构造函数。如下:

#include

#include

using namespace std;

class CopyTest

{

public:

char *buf;

CopyTest()

{

cout << "调用默认构造函数!" <

//i = 3;

buf = (char*)malloc(50);

}

//COPY构造函数

CopyTest( CopyTest &obj)

{

cout << "调用拷贝构造函数!"<

i = 10;

buf = (char*)malloc(50);

strcpy(buf,obj.buf);

}

相关文档
最新文档