小满的C++学习心得(2) 说说类构造函数和动态内存管理

早就听说C++难就难在它的内存管理,new和delete使用的一不小心轻则内存泄漏,重则损坏堆内存抛出异常。C++异常不同于一般的bug,定位和跟踪颇为困难,最近我在做《C++ Primer Plus 5th Edition》第12章第2道编程题时就吃够了它的苦头。到头来发现她是因为我内存管理不善引起的,或者也可说是对构造函数不敏感引起的。

 

这则程序主要的功能就是做一个类模拟C++内置的string类的功能,以下是这个类的头文件定义,其中私有成员str是用于储存字符串内容的,其空间由构造函数在使用时按需求用new分配:

这个类功能比较多,在此文中不一一说明其功能。它其中一部分是书上的代码,一部分是我添加的。我要主要说的是我出问题的部分,也就是那三个对“+”号的重载函数。+号在此的作用是拼接两个字符串类为一个,先定义一个临时String类temp,将前一个字符串类用复制构造函数整体拷贝给temp,然后再把下一个类的字符串内容用strcat()函数拼接上去:

 

使用了以下main()函数调用后,出现了一些奇怪的问题。在VS2008下用Debug模式编译时随着输入内容的不同随机出现了std::bad_alloc异常,用Release模式编译则异常每次都会出现:

根据单步跟踪的结果,确定问题出现在重载“+”的函数上。(以上main函数只是为了说明问题而写,原程序很长,我花了很长时间才确定病灶所在。)

 

想了半天,想出了个馊主意,不使用原来的复制类的方式,把表示前一半字符串的类中的str字符串全部用strcpy()的方式直接复制给temp里的str成员:

 

这下子问题变得更加糟糕,无论是在Debug还是Release模式下都抛出了异常。功夫不负有心人,经过我仔细研究,终于发现病灶所在。首先,上面的程序用了String temp;这个语句来初始化类,它没有参数,因此调用了默认构造函数,默认构造函数的定义如下:

在默认构造函数中,成员str只被分配了一个字节的空间。因此,后面的无论是strcpy还是strcat都是在操作没有被合法分配的内存空间,抛出异常是必然的。那么前个错误版本呢?它使用了对“=”的重载对类进行直接复制,为什么也不可行?这是“=”重载的定义:

成员str只被分配了与等号右值的类相同大小的存储空间,没有余量。因此在后面接着使用strcat拼接也是非法操作,因为后面没有合法的内存空间了。最后,我想出了一个可行的解决方案:

它先定义一个临时的char*字符串指针,紧接着分配目标大小的空间。在这个char字符串里完成拼接后整体利用一个一字符串数组为参数的构造函数新建一个对象用于结果的传递,该构造函数定义如下:

传递给它的字符串有多长,它就分配多少空间,以上问题就此完全解决。

 

 

通过整个过程,我认识到了内存管理对C++的重要性。同时,我们在以后定义对象是要时刻回头想想这个类的构造函数是怎么定义的,新定义的对象它的成员的初始状态是什么,这样能够避免许多不必要的麻烦。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值