C++大三法则相关问题

最近,曾老师再讲C++,讲到C++大三法则,不同特来搜索,总结如下:

C++三法则:如果需要析构函数,则一定需要拷贝构造函数和赋值操作符。

如何理解这句话,首先,从“如果需要析构函数”这里我们知道,类中必然出现了指针类型的成员(否则不需要我们写析构函数,默认的析构函数就可以用了),所以,我们需要自己写析构函数来释放给指针所分配的内存来防止内存泄露,那么为什么说“一定需要拷贝构造函数和赋值操作符”呢,原因还是这样:类中出现了指针类型的成员。有指针类型的成员,我们必须防止浅拷贝问题,所以,一定需要拷贝构造函数和赋值操作符,这两个函数是防止浅拷贝问题所必须的。  ----- piaopiaohu123

 

这里涉及到了浅拷贝,下面说明一下浅拷贝:

class test {
public:
 test(int _data)             //有参数构造函数
  : data(_data) {}
 test(){}                    //无参数构造函数
private: 
 int data;
};
int main()
{
 test a(5);
     test b = a; // 仅仅是数据成员之间的赋值

return 0;
 }

这一句b = a;就是浅拷贝,执行完这句后b.data = 5;


如果对象中没有其他的资源(如:堆,文件,系统资源等),则深拷贝和浅拷贝没有什么区别,但当对象中有这些资源时,

例子:

class A {
public:
 A(int _size): size(_size)
  {
    data = new int[size];
  } // 假如其中有一段动态分配的内存 A(){}; ~A(){delete [] data;} // 析构时释放资源
private:
 int* data;
 int size;
};
int main()
{
 A a(5), b = a; // 注意这一句
 return 0;
 }

这里的b = a会造成未定义行为,因为类A中的复制构造函数是编译器生成的,所以b = a执行的是一个浅拷贝过程。我说过浅拷贝是对象数据之间的简单赋值,比如:
b.size = a.size; b.data = a.data; // Oops!
这里b的指针data和a的指针指向了堆上的同一块内存,a和b析构时,b先把其data指向的动态分配的内存释放了一次,而后a析构时又将这块已经被释放过的内存再释放一次。
对同一块动态内存执行2次以上释放的结果是未定义的,所以这将导致内存泄露或程序崩溃。
所以这里就需要深拷贝来解决这个问题,深拷贝指的就是当拷贝对象中有对其他资源(如堆、文件、系统等)的引用时(引用可以是指针或引用)时,对象的另开辟一块新的资源,而不再对拷贝对象中有对其他资源的引用的指针或引用进行单纯的赋值。如:
class A { public: A(int _size) : size(_size){data = new int[size];} // 假如其中有一段动态分配的内存 A(){}; A(const A& _A) : size(_A.size){data = new int[size];} // 深拷贝 ~A(){delete [] data;} // 析构时释放资源
private: int* data; int size; }
int main() { A a(5), b = a; // 这次就没问题了 }
总结:
深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝。-----xdx2ct1314

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值