码迷,mamicode.com
首页 > 其他好文 > 详细

深拷贝 浅拷贝 以及赋值运算符= 的重载

时间:2014-05-13 05:29:10      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:style   blog   class   code   c   ext   

在一些程序当中,需要将一个对象里的值直接传递给另一个对象,需要进行对象的拷贝。但是在某些情况下也会出现错误,如类内部成员需要动态开辟内存,实行位拷贝,就是将一个对象的值完全复制给另一个对象,如A=B,但如果B中也有一个指针申请了内存,那么A中的成员变量也指向了同一块内存,如果当释放资源的时候,就会导致野指针的出现,出现错误。

深拷贝的简单理解 就是在复制对象内容的过程中,需要重新分配资源,而浅拷贝则是不要重新分配资源。但是浅拷贝存在着问题:当资源释放时会产生资源归属不清的问题,导致运行错误。

当自己书写拷贝函数的时候,类中本身默认的拷贝函数已经不存在,此时需要在拷贝函数处理所需处理的所有数据。

拷贝和赋值:

当对象在声明的时候即用另一个对像进行初始化 即称为拷贝。如果是在声明之后,在进行赋值操作,则需要重载赋值操作符。

结合代码:

#include <iostream>
#include <cstring>
using namespace std;

class A{
    private:
        char* data;
    public:
        A(){}
        A(char* num){
            int len = strlen(num)+1;
            data = new char[len];
            strcpy(data,num);
            cout<<data<<endl;
        }

        ~A(){
            delete[] data;
        }

        void show(){
            cout<<data<<endl;
        }
};

int main(){
    A a("hahah");
    A b;
    b = a;
    b.show();
    A c(a);
    c.show();
    return 0;
}

默认在缺省状态下的赋值操作符 执行 b=a 内存分析:

bubuko.com,布布扣

A,B 指向了同一个内存地址,此时不会出现问题,但是在析构的同时,会出现俩个指针同时释放相同的内存地址,则会出现错误。

需要通过重载赋值运算符进行处理:

#include <iostream>
#include <cstring>
using namespace std;

class A{
    private:
        char* data;

    public:
        A(){}
        A(char* num){
            int len = strlen(num)+1;
            data = new char[len];
            strcpy(data,num);
            cout<<data<<endl;
        }

        //浅拷贝
        //      A(const A& o):data(o.data){}

        //拷贝构造函数  深拷贝
       A(const A& o){
           int len = strlen(o.data)+1;
           data = new char[len];
           if(data!=NULL)
                strcpy(data,o.data);
        }

        //赋值运算符的重载

        A& operator=(const A& o){
            if(this == &o)
                return *this;
            delete[] data;
            data = NULL;

            data = new char[strlen(o.data)+1];
            strcpy(data,o.data);
            return *this;
        }

        ~A(){
            delete[] data;
        }

        void show(){
            cout<<data<<endl;
        }
};

int main(){
    A a("hahah");
    A b;
    b = a;
    b.show();
    A c(a);
    c.show();
    return 0;
}

需要的内存分析应该是这样的:

bubuko.com,布布扣

注:

1.不要在调用构造函数时向其传递对象,应该传递对象的引用。因为传递对象的时候,还是需要调用构造函数,之后向其传入的还是对象,又再一次的调用构造函数,...,如此循环继续下去,导致段错误(栈溢出)。

2.在进行拷贝构函数的时候 函数不需要返回值,但是在进行赋值操作符的时候,需要有返回值,void类型,类的本身,或者是类的引用。

然而 返回是void的时候,不支持链式的赋值即: a=b=c=d...

返回类型的是类的本身

A operator=(const A& o){
            if(this == &o)
                return *this;
            delete[] data;
            data = NULL;

            data = new char[strlen(o.data)+1];
            strcpy(data,o.data);
            return *this;
        }

具体步骤是:
(1)释放元内存资源

(2)申请一块新的内存空间

(3)原堆内存的值赋值到新的内存

(4)创建临时对象(调用拷贝构造函数),返回临时对象

(5)临时对像结束,调用析构函数,释放对象内存

返回类型如果是对象的引用:

A& operator=(const A& o){
            if(this == &o)
                return *this;
            delete[] data;
            data = NULL;

            data = new char[strlen(o.data)+1];
            strcpy(data,o.data);
            return *this;
        }

具体步骤:

(1)释放原内存资源

(2)申请新的内存资源

(3)原值赋值到新的内存

(4)结束

返回对象的引用 不需要调用拷贝构造函数,提高效率,建议采纳。


深拷贝 浅拷贝 以及赋值运算符= 的重载,布布扣,bubuko.com

深拷贝 浅拷贝 以及赋值运算符= 的重载

标签:style   blog   class   code   c   ext   

原文地址:http://blog.csdn.net/xd_122/article/details/25624477

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!