开发者社区> 异步社区> 正文

《C++面向对象高效编程(第2版)》——4.3 C++中的无用单元收集

简介:
+关注继续查看

本节书摘来自异步社区出版社《C++面向对象高效编程(第2版)》一书中的第4章,第4.3节,作者: 【美】Kayshav Dattatri,更多章节内容可以访问云栖社区“异步社区”公众号查看。

4.3 C++中的无用单元收集

C++面向对象高效编程(第2版)
C++提供类的析构函数专门处理无用单元收集,但是,这并不意味着无用单元收集只发生在析构函数中。实际上,某些其他成员函数也必须考虑无用单元收集。

类的析构函数给予对象最后一次机会释放它所获得的所有资源。在退出某作用域之前,由语言自动为在该作用域中创建的自动(基于栈)对象调用析构函数。此时,对象即将被销毁(也就是说,被对象占用的内存即将被系统回收)。一旦析构函数完成,对象将彻底地消失。

删除(使用delete操作符)指向某对象的指针时,将通过该对象调用对象所属类的析构函数。

TPerson *p;
p = new TPerson(“12-25-95”); // 在堆上创建一个TPerson类对象
// ...
delete p; // 这将通过p所指向的对象,调用TPerson类的析构函数```。
在析构函数执行完毕后,p所指向的内存被释放。TPerson类的构造函数和析构函数的实现,如下所示:

// 第一个构造函数
TPerson::TPerson(const char birthDate[])
    : _ssn(0), _name(0), _birthDate(birthDate), _address(0)
    { / 构造函数体无代码 / }
char Strdup (const char src)  // 辅助函数
{
  char* ptr = new char[strlen(src)+1];
  strcpy(ptr, src);  
  return ptr;
}
// 第二个构造函数
TPerson::TPerson(const char theName[], const char theAddress[],
     unsigned long theSSN, const char theBirthDate[])
   : _ssn(theSSN), _birthDate(theBirthDate)
{ // 初始化_name、_address等
  _name = (theName ? Strdup(theName) : 0);
  _address = (theAddress ? Strdup(theAddress) : 0);
}`
我们已在堆(heap)上为待储存人名中的字符分配内存。析构函数负责释放这些内存。

// 析构函数
TPerson::~TPerson()
{
    delete [] _name;
    delete [] _address;
}```
现在,考虑下面一段代码:

main()
{
    TPerson john(“11-23-45”);
    // ...
    john.SetName(“John Wayne”);
}`
对象john只有出生日期,没有姓名。接下来,我们使用SetName成员函数设置john的姓名。SetName成员函数用来做什么?以下是它的实现代码:

void TPerson::SetName(const char newName[])
{
   unsigned oldLength = _name ? strlen(_name) : 0;
   unsigned newLength = newName ? strlen(newName) : 0;
   if (oldLength < newLength) { // _name中没有足够的空间
     delete [] _name;  // 无用单元收集
     // 使用已定义的Strdup函数
     _name = (newName ? Strdup(newName) : 0);
   }
   else {
     if (newName) strcpy(_name, newName);
     else {delete [] _name; _name = 0;}
   }
}```
我们检查_name中的字符个数是否足够容纳newName,如果不够就删除_name并分配一块新内存。在分配新内存之前,一定要记得释放_name中的存储区,这非常重要。这就是我们所说的生存期内获得资源。对象john的析构函数仍将正常工作,因为_name确保指向有效内存或者为0。

回顾TCar类的例子,当销毁TCar类的对象时,该对象中的对象_owner怎么办?幸运地是,语言提供了帮助。当TCar类对象即将被销毁时,语言将调用包含在TCar类对象中的对象_owner(TPerson类型)的析构函数,确保不会发生资源泄漏。一般而言,在对象即将被销毁时,包含在该对象中的所有对象的析构函数将被递归地调用,直至所有被包含的对象都被销毁。这只适用于按值包含在其他对象中的对象。如果某对象包含指向其他对象的指针,则由析构函数负责显式销毁它们。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
少儿编程持续火热,“BrickCode 贝壳编程”获 500 万元天使轮融资
近日,8 - 16 岁少儿编程品牌“BrickCode 贝壳编程”(后简称为贝壳编程)完成 500 万元天使轮融资,投资方为个人投资方和内部员工。
303 0
01.C++(一)----面向对象的思想
(创建于2017/12/20) 1.命名空间 namespace :C++引入的用于解决多个模块间命名冲突问题的一个机制,他是一个由程序设计者命名的内存区域,程序设计者可以根据需要指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分隔开来。
913 0
c++编程思想2 --友元存储控制
 友元friend在c++中的应用  我们知道在c++的类访问权限中,private和 protected在类外面进行访问的时候 会因为权限而不能访问 ,友元就解决了这个问题 。 可以这样理解,他为外部的 函数 或者类 进行了 访问授权,其实这已经超出OOP的范畴,但是对于C++而言是以实用为主,所以说C++并不是完全面向对象的语言 C++这一特性就破坏的C++的安全性 。
753 0
少儿编程妙小程完成近千万美元A轮融资,创世伙伴领投
妙小程成立于2017年4月,始终坚持“打造有温度的科技,用有趣的方式拥抱教育”的理念,不断优化编程平台、更新编程课程、改善用户体验。
293 0
+关注
异步社区
异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。
12049
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载