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

    xiaoxiao2024-08-18  98

    本节书摘来自异步社区出版社《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类型)的析构函数,确保不会发生资源泄漏。一般而言,在对象即将被销毁时,包含在该对象中的所有对象的析构函数将被递归地调用,直至所有被包含的对象都被销毁。这只适用于按值包含在其他对象中的对象。如果某对象包含指向其他对象的指针,则由析构函数负责显式销毁它们。 相关资源:Java Web编程宝典-十年典藏版.pdf part1(共2个)
    最新回复(0)