MST

星途 面试题库

面试题:C++中指针在内存管理与多态的综合应用

假设有一个基类`Base`和一个派生类`Derived`,`Base`中有一个虚函数`print`。在堆上创建`Derived`对象,并使用`Base*`指针指向它。编写代码实现通过该指针调用`print`函数,展示多态特性。同时,详细描述在这个过程中内存是如何分配和释放的,以及可能出现的内存泄漏问题及解决方案。
34.0万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>

class Base {
public:
    virtual void print() {
        std::cout << "This is Base::print()" << std::endl;
    }
    virtual ~Base() {} // 确保析构函数是虚函数,防止内存泄漏
};

class Derived : public Base {
public:
    void print() override {
        std::cout << "This is Derived::print()" << std::endl;
    }
    ~Derived() {}
};

int main() {
    Base* ptr = new Derived();
    ptr->print(); // 调用Derived类的print函数,展示多态特性
    delete ptr;
    ptr = nullptr;
    return 0;
}

内存分配和释放过程

  1. 内存分配
    • new Derived()语句在堆上为Derived对象分配内存。由于Derived继承自BaseDerived对象的内存布局会包含Base部分和Derived自身新增的部分。同时,因为Base中有虚函数,会在对象内存的起始位置放置一个虚函数表指针(vptr),指向虚函数表(vtable),虚函数表中存放着虚函数的实际地址。
  2. 内存释放
    • delete ptr;语句释放ptr指向的堆内存。由于Base的析构函数是虚函数,当delete ptr时,首先调用Derived的析构函数,然后调用Base的析构函数,正确地释放Derived对象占用的所有内存。如果ptr赋值为nullptr,可以防止野指针的产生。

可能出现的内存泄漏问题及解决方案

  1. 内存泄漏问题
    • 如果Base的析构函数不是虚函数,当delete ptr;执行时,只会调用Base的析构函数,而不会调用Derived的析构函数,Derived类中动态分配的资源(如果有)就无法释放,从而导致内存泄漏。
  2. 解决方案
    • Base的析构函数声明为虚函数,如上述代码中virtual ~Base() {},这样在delete指向派生类对象的基类指针时,会先调用派生类的析构函数,再调用基类的析构函数,确保对象占用的所有内存都被正确释放。同时,在delete后将指针赋值为nullptr,防止野指针的产生。