MST

星途 面试题库

面试题:C++常对象与动态内存管理的交互

假设你有一个包含动态分配成员(如指针指向堆内存)的常对象类。请说明在对象的构造、析构以及拷贝构造函数中,如何正确管理内存以避免内存泄漏,同时满足常对象的特性要求。并举例说明在实际代码中可能出现的错误场景及解决办法。
49.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
  1. 构造函数
    • 在构造函数中,为动态分配的成员(如指针指向的堆内存)分配内存。确保在分配内存后进行检查,以防止分配失败。
    • 例如:
class MyClass {
private:
    int* data;
public:
    MyClass(int size) {
        data = new int[size];
        if (!data) {
            throw std::bad_alloc();
        }
        // 初始化数组等操作
        for (int i = 0; i < size; ++i) {
            data[i] = i;
        }
    }
};
  1. 析构函数
    • 在析构函数中,释放动态分配的内存。对于指针类型的成员,使用delete(如果是单个对象)或delete[](如果是数组)来释放内存。
    • 例如:
class MyClass {
private:
    int* data;
public:
    ~MyClass() {
        delete[] data;
    }
};
  1. 拷贝构造函数
    • 对于常对象类,拷贝构造函数也需要正确管理内存。它应该执行深拷贝,即分配新的内存,并将源对象的数据复制到新分配的内存中。
    • 例如:
class MyClass {
private:
    int* data;
public:
    MyClass(const MyClass& other) {
        int size = 10; // 假设这里知道源对象数组大小,实际可能需要更复杂逻辑获取大小
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = other.data[i];
        }
    }
};
  1. 错误场景及解决办法
    • 浅拷贝问题
      • 错误场景:如果拷贝构造函数只是简单地复制指针,而不是分配新的内存并复制数据,就会导致浅拷贝。这样,当两个对象共享同一块内存时,析构函数会尝试释放同一块内存两次,导致未定义行为。
class MyClass {
private:
    int* data;
public:
    MyClass(int size) {
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = i;
        }
    }
    // 错误的拷贝构造函数(浅拷贝)
    MyClass(const MyClass& other) {
        data = other.data;
    }
    ~MyClass() {
        delete[] data;
    }
};

在上述代码中,当MyClass对象被拷贝时,两个对象的data指针指向同一块内存。当其中一个对象被销毁时,这块内存被释放,另一个对象的data指针就变成了野指针。当另一个对象也试图销毁时,就会导致未定义行为。 - 解决办法:实现深拷贝,如上面正确的拷贝构造函数示例,分配新的内存并复制数据。

  • 内存分配失败未处理
    • 错误场景:在构造函数中,如果内存分配失败(例如系统内存不足),而没有进行适当处理,可能会导致程序崩溃。
class MyClass {
private:
    int* data;
public:
    MyClass(int size) {
        data = new int[size];
        // 未检查内存分配是否成功
        for (int i = 0; i < size; ++i) {
            data[i] = i;
        }
    }
    ~MyClass() {
        delete[] data;
    }
};
 - **解决办法**:在内存分配后检查返回值,如构造函数示例中,在`new`操作后检查`data`是否为`nullptr`,如果是则抛出异常。这样可以确保程序在内存分配失败时能够进行合理的错误处理。