c\c++复习基础要点11----对象的浅拷贝和深拷贝

默认的拷贝构造函数与对象的浅拷贝问题

 

如果定义类时,没有为其声明拷贝构造函数,则编译器会为类自动生成一个拷贝构造函数,这个由编译器自动生成的拷贝构造函数称为默认的拷贝构造函数。默认的拷贝构造函数的功能就是把参数对象内容按字节拷贝给当前正在创建的对象。

 

 

对象的浅拷贝:

 

#include<iostream>

using namespace std;

 

class A

{

 public:

A()

{

     numptr = new int(1);

}

 

A(int  num)

{

     numptr = new int(num);

}

~A()

{

     delete numptr;

}

 

void setnum(int  num)

{

     *numptr = num;

}

 

int  getnum()

{

      return *numptr;

}

 

 private:

   int  *numptr;

};

 

void main()

{

    A a1(10);

    A a2=a1;

     cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;

     cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;

    a1.setnum(20);

     cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;

     cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;

 

}

 

运行结果:

对象a1中存放的整数位:10

对象a2中存放的整数位:10

对象a1中存放的整数位:20

对象a2中存放的整数位:20

 

分析:

对象的浅拷贝是产生这种现象的根本原因:

   当执行语句A a2=a1时,需要调用默认拷贝构造函数,该函数a1按字节拷贝给对象a2,导致对象a1的整数指针numptr和对象a2的整数指针numptr指向“堆”中的同一个整数,所以当通过对象a1的成员numptr修改其指向的整数值时,自然会影响到对象a2。这种情况称为对象的浅拷贝。

 

 

对象间正确的拷贝方法应该使得不同的对象间不存在任何共享数据,称这种拷贝为深拷贝

 

解决方案:自定义拷贝构造函数

 

为类添加拷贝构造函数,以实现对象的深拷贝:

 

#include<iostream>

using namespace std;

 

class A

{

 public:

A()

{

     numptr = new int(1);

}

 

A(int  num)

{

     numptr = new int(num);

}

A(A&);

~A()

{

     delete numptr;

}

 

void setnum(int  num)

{

     *numptr = num;

}

 

int  getnum()

{

      return *numptr;

}

 

 private:

   int  *numptr;

};

 

A::A(A& a)

{

     numptr= new int(*a.numptr);

    cout<< “类的拷贝构造函数被调用”<<endl

}

 

void main()

{

    A a1(10);

    A a2=a1;

     cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;

     cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;

    a1.setnum(20);

     cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;

     cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;

 

}

 

运行结果:

对象a1中存放的整数位:10

对象a2中存放的整数位:10

对象a1中存放的整数位:20

对象a2中存放的整数位:10

 

 

 

由赋值运算操作引发的对象浅拷贝

 

#include<iostream>

using namespace std;

 

class A

{

 public:

A()

{

     numptr = new int(1);

}

 

A(int  num)

{

     numptr = new int(num);

}

A(A&);

~A()

{

     delete numptr;

}

 

void setnum(int  num)

{

     *numptr = num;

}

 

int  getnum()

{

      return *numptr;

}

 

 private:

   int  *numptr;

};

 

A::A(A& a)

{

     numptr= new int(*a.numptr);

    cout<< “类的拷贝构造函数被调用”<<endl

}

 

void main()

{

    A a1(10);

    A a2;

     a2=a1;

     cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;

     cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;

    a1.setnum(20);

     cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;

     cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;

 

}

 

运行结果:

对象a1中存放的整数位:10

对象a2中存放的整数位:10

对象a1中存放的整数位:20

对象a2中存放的整数位:20

该程序是a2=a1使用了赋值操作符,默认情况下的赋值操作所完成的任务就是将赋值号右边的对象内容按字节拷贝给赋值号左边的对象,则也出现了浅拷贝现象。

 

解决:自定义赋值运算符

 

#include<iostream>

using namespace std;

 

class A

{

 public:

A()

{

     numptr = new int(1);

}

 

A(int  num)

{

     numptr = new int(num);

}

A(A&);

~A()

{

     delete numptr;

}

 

void setnum(int  num)

{

     *numptr = num;

}

 

int  getnum()

{

      return *numptr;

}

A&operator=(A);

 

 private:

   int  *numptr;

};

 

A::A(A& a)

{

     numptr= new int(*a.numptr);

    cout<< “类的拷贝构造函数被调用”<<endl

}

 

A& A::operator =(A a)

{

     numptr=  new int(*a.numptr);

     return*this;

}

 

void main()

{

    A a1(10);

    A a2;

     a2=a1;

     cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;

     cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;

    a1.setnum(20);

     cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;

     cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;

 

}

 

运行结果:

对象a1中存放的整数位:10

对象a2中存放的整数位:10

对象a1中存放的整数位:20

对象a2中存放的整数位:10

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值