MST

星途 面试题库

面试题:C++ 赋值运算符与拷贝构造函数引发的内存管理问题探讨

假设有一个自定义类MyClass,其内部包含动态分配的内存(如通过new分配了一个int数组)。在实现赋值运算符和拷贝构造函数时,如何正确处理内存管理以避免内存泄漏和悬空指针问题?请写出完整的类定义及两个函数的实现代码,并解释其中的关键步骤。
26.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>

class MyClass {
private:
    int* data;
    int size;
public:
    // 构造函数
    MyClass(int s) : size(s) {
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = 0;
        }
    }

    // 拷贝构造函数
    MyClass(const MyClass& other) : size(other.size) {
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = other.data[i];
        }
    }

    // 赋值运算符重载
    MyClass& operator=(const MyClass& other) {
        if (this != &other) {
            delete[] data;
            size = other.size;
            data = new int[size];
            for (int i = 0; i < size; ++i) {
                data[i] = other.data[i];
            }
        }
        return *this;
    }

    // 析构函数
    ~MyClass() {
        delete[] data;
    }

    void printData() {
        for (int i = 0; i < size; ++i) {
            std::cout << data[i] << " ";
        }
        std::cout << std::endl;
    }
};

关键步骤解释:

  1. 拷贝构造函数

    • 首先根据源对象的size分配新的内存空间。
    • 然后将源对象data数组中的内容逐个复制到新分配的内存中。这样就保证了新对象有自己独立的内存,而不是和源对象共享内存,避免了悬空指针问题。
  2. 赋值运算符重载

    • 首先检查是否是自我赋值(this != &other),如果是自我赋值则直接返回*this,避免不必要的操作。
    • 如果不是自我赋值,先释放当前对象已分配的内存(delete[] data),防止内存泄漏。
    • 然后根据源对象的size分配新的内存空间,并将源对象data数组中的内容逐个复制到新分配的内存中。最后返回*this以便支持链式赋值。
  3. 析构函数:在对象销毁时,释放动态分配的内存(delete[] data),防止内存泄漏。