MST

星途 面试题库

面试题:C++ 类缺省函数默认行为与内存管理

假设有一个类`class Resource { char* buffer; int size; public: // 此处未定义任何缺省函数 };`,由于没有显式定义缺省函数,编译器会生成默认版本。请分析在使用默认拷贝构造函数和默认赋值运算符重载函数时,可能会出现哪些内存管理问题,并说明原因。如何通过自定义这些缺省函数来避免这些问题?
47.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 使用默认拷贝构造函数和默认赋值运算符重载函数可能出现的内存管理问题及原因

  • 内存泄漏:默认拷贝构造函数只是简单地按位拷贝成员变量。对于Resource类,这意味着buffer指针会被拷贝,而不是其指向的内存。当两个Resource对象都指向同一块内存,且其中一个对象被销毁时,这块内存会被释放。如果另一个对象还试图访问这块已释放的内存,就会导致未定义行为。并且,如果每个对象都尝试释放这块内存(例如在析构函数中),就会出现重复释放,导致内存泄漏。
  • 悬空指针:在默认赋值运算符重载函数中,同样只是简单地按位赋值成员变量。如果目标对象之前已经分配了内存,这块内存不会被正确释放,从而导致内存泄漏。而且,新赋值的buffer指针指向的内存与源对象指向的内存相同,当源对象被销毁,释放了这块内存后,目标对象的buffer就成为了悬空指针,再次访问会导致未定义行为。

2. 自定义缺省函数避免这些问题的方法

  • 自定义拷贝构造函数
Resource::Resource(const Resource& other) {
    size = other.size;
    buffer = new char[size];
    std::copy(other.buffer, other.buffer + size, buffer);
}

此拷贝构造函数为新对象分配了独立的内存,并将源对象buffer中的内容复制到新分配的内存中,避免了内存共享带来的问题。

  • 自定义赋值运算符重载函数
Resource& Resource::operator=(const Resource& other) {
    if (this != &other) {
        delete[] buffer;
        size = other.size;
        buffer = new char[size];
        std::copy(other.buffer, other.buffer + size, buffer);
    }
    return *this;
}

在自定义赋值运算符重载函数中,首先检查是否是自我赋值。如果不是,先释放目标对象已分配的内存,然后重新分配内存并复制源对象的内容,从而避免内存泄漏和悬空指针问题。