C++拷贝构造函数详解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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); }