【C++】拷贝构造函数

在基本数据类型的初始化中,如
int a=b;
编译器只要将b的值作为a的初始值。
假设我们已定义类型Test,且有一个已经初始化的Test型对象x,如果我们希望定义一个新的Test型对象y,并且将x的值作为y的初始值,可以使用下面的语句:
Test y(x);
或者 Test y=x;
上述语句均是合法的,它只是简单地把x的成员一一复制给y,当然我们还可以重载赋值符=,这里不再详述。
由于类对象往往含有多个成员,拷贝构造函数便很重要。那么,什么时候编译器会调用拷贝构造函数?
1.用一个类对象初始化另一个类对象。
2.对象按值传递方式传入函数体。
3.对象按值传递方式从函数返回。
下面举一个使用拷贝构造函数的例子:
#include<iostream>

using namespace std;

class Test
{
public:    //为叙述方便,将访问权限设为public
    int a;
    int b;
    Test(){}
    Test(int m,int n):a(m),b(n){}
    Test(const Test& t)
    {
        a=t.a;
        b=t.b;
    }
};

void main()
{
    Test x(1,2);
    Test y(x);
    cout<<y.a<<'\t'<<y.b<<endl;
}
程序将输出1    2。
这里将x的成员一一复制给了y的成员。既然不用自己写拷贝构造函数,也可以实现这个效果,为什么还要浪费这个力气?这里我们可以“选择”性拷贝,比如只复制成员a的值,从而实现将对象初始化为特定的状态。
需要注意的是,如果在类定义中,我们没有显示地声明一个拷贝构造函数,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝,“位拷贝”又称“浅拷贝”。所以我们虽然没有声明拷贝构造函数,也可以使用Test y(x);这样的语句。
相对于“浅拷贝”,还有一种方式称为“深拷贝”,下面讨论两者的区别:
简单地说,“浅拷贝”就是就将对象的值直接复制给另一对象。然而,假设类中我们定义了一个指针成员,并且该指针已经向系统申请内存,那么通过浅拷贝的方式初始化另一对象之后,如果原对象的指针指向的内存已经被回收(如析构),我们用该对象初始化的“另一对象”的这个指针将变成野指针,从而导致程序运行出错,因为我们“浅拷贝”了原指针的值(地址),并没有分配新的内存,从而两个指针指向同一内存区域。
假设原对象已有堆资源,如果我们在拷贝的过程中分配新的堆资源给另一对象,这种方式就叫做“深拷贝”,它避免了出现野指针的问题。
下面举个深拷贝的实例:
#include<iostream>
#include<string>

using namespace std;

class Test
{
public:
    int num;
    char* str;
    Test(){}
    Test(int n,char* s)
    {
        num=n;
        str=new char[num];
        strcpy(str,s);
    }
    Test(const Test& t)
    {
        num=t.num;
        str=new char[num];   //深拷贝
        strcpy(str,t.str);
    }
    ~Test(){    delete str;    }
};

void main()
{
    ……
}
上述代码中的函数strcpy()为C的一个标准库函数,原型声明:extern char *strcpy(char *dest,const char *src);
头文件:string.h
功能:把从src地址开始且含有NULL结束符的字符串赋值到以dest开始的地址空间 
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。 
返回指向dest的指针。

可以总结,拷贝构造函数的声明方式为:
ClassName(ClassName& ObjName); 
或ClassName(const ClassName& ObjName);
需要指出的是,必须按引用传递参数,否则在调用构造函数之前,首先要将实参拷贝给形参,这一过程又将调用拷贝构造函数,形成递归死循环,好在编译器会检查这种逻辑性,错误的声明不会编译通过。

以上实例均测试通过。

欢迎批评指正!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值