C++之一些事一些情--深拷贝和浅拷贝

来源:互联网 发布:.top域名怎么样 编辑:程序博客网 时间:2024/06/05 00:31

1、拷贝构造函数的出现场景

       以下是String类的一个简单定义,用于说明一些例子:

class String{public:    String(const char *ch=NULL);//默认构造函数    String(const String &str);//拷贝构造函数    ~String(void);//析构函数    String& operator=(const String &str);//赋值构造函数private:    char *m_data;};

       当用一个已初始化的类类型对象初始化一个新的对象时,拷贝构造函数就会被调用,拷贝构造函数会出现在以下三种情景:


1) 一个对象以值传递的方式传入函数体

void InputString(String obj){    //函数具体逻辑}

2) 一个对象以值传递的方式从函数返回

String OutputString(){        return String("hello world");}

3) 使用一个对象初始化另一个对象

String a(1);String b = a;//通过对象a初始化对象b


2、深拷贝和浅拷贝的区别

       深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。
       当用户没有自定义拷贝构造函数时,编译器会自动生成一个默认的拷贝构造函数,并以位拷贝(位拷贝就是浅拷贝)的方式完成对象之间的赋值。关于深拷贝和浅拷贝的一个经典例子就是String类的实现,以下代码使用一个String类对象初始化另一个String类对象:

String a("Shallow Copy");String b = a;

       若上面的代码没有重写拷贝构造函数,就会出现以下的问题:
       1) 对象a和对象b的成员变量m_data将会指向了同一内存区域,其中一方的改变将会影响另一方;
       2) 当对象析构的时候,对象a的成员变量m_data将会被析构两次,造成程序崩溃。


3、拷贝构造函数和赋值构造函数

       所谓赋值构造函数,就是操作符"="的重载函数,它的作用与拷贝构造函数类似,若没有重写赋值构造函数,编译器也会自动生成一个默认的以位拷贝工作的赋值构造函数。

String a("hello");String b("world");b = a;

       若上面的代码没有重写赋值构造函数,则会出现以下问题:
       1) 对象b的成员变量m_data原来指向的内存区域没有被释放,造成内存泄露;
       2) 对象a和对象b的成员变量m_data将会指向了同一内存区域,其中一方的改变将会影响另一方
       3) 当对象析构的时候,对象a的成员变量m_data将会被析构两次,造成程序崩溃。

       不是说有等于号的时候就是赋值构造函数,有的时候拷贝构造函数和赋值构造函数容易混淆,看以下例子:

String a("hello");String b("world");String d = a;//拷贝构造函数b = a;//赋值构造函数

       当用一个已存在的对象初始化一个未存在的对象时,调用的是拷贝构造函数;当用一个已存在的对象给另一个已存在的对象赋值时,调用的是赋值构造函数,它也仅出现在这种情况。
       为了设计出更安全的类,需要使用到拷贝构造函数和赋值构造函数时,则重写一个深拷贝的版本;若不需要,则禁用这两个函数,免得出现一些不应该的错误。只要对拷贝构造函数和赋值构造函数的函数访问级别设置为private即可以禁用这两个函数,以前面的String简单定义代码为例子:

class String{public:    String(const char *ch=NULL);//默认构造函数~String(void);//析构函数private:    String(const String &str);//拷贝构造函数    String& operator=(const String &str);//赋值构造函数private:    char *m_data;};


9 0
原创粉丝点击