C++多态对象vector与unique_ptr内存泄漏问题咨询
关于C++多态内存管理与避免内存泄漏的疑问
问题背景
我在完成作业时尝试规范管理内存,遇到了一些疑问:
- 想要创建存储父类、子类对象的
vector,比如vector<Parent> list,知道需要用指针避免对象切割,所以考虑vector<Parent*>。 - 了解到C++智能指针,但听说父类析构函数调用时(比如智能指针超出作用域)可能引发内存泄漏,不清楚怎么编写类来避免。
我写了一段示例代码,输出是"This is A",我认为这意味着通过指针调用析构函数会导致内存泄漏:
class A{ public: virtual void funct(){ cout << "This is A" << endl; } }; class B : public A{ public: void funct(){ cout << "This is B" << endl; } }; int main() { B b; auto ptr = make_unique<A>(b); ptr.get()->funct(); return 0; }
参考建议后修改了代码,给父类加了虚析构函数,子类也重写了析构函数,想问这样是否足以避免内存泄漏?也就是销毁unique_ptr ptr时,会不会释放B对象占用的内存?
class A{ public: virtual void funct(){ cout << "This is A" << endl; }; virtual ~A() = default; }; class B : public A{ public: void funct() override{ cout << "This is B" << endl; } ~B() override = default; }; int main() { B b; unique_ptr<A> ptr = make_unique<B>(b); ptr->funct(); return 0; }
解答
第一段代码的核心问题
你第一段代码的问题不是析构导致的内存泄漏,而是对象切割:
make_unique<A>(b)是把B对象b拷贝构造了一个纯A类型的对象存到堆上,ptr指向的本质就是一个A对象,而非B对象,所以调用funct()只会触发A的版本,输出"This is A"。- 这里不存在子类内存未释放的问题,因为堆上本来就只有一个
A对象,析构时只会调用A的析构函数,但这种写法完全没用到多态,根本达不到你存储子类对象的目的。
修改后的代码是否能避免内存泄漏
修改后的代码完全满足多态下安全释放内存的要求:
- 父类虚析构是核心:当父类析构函数被声明为虚函数时,通过父类指针/智能指针销毁子类对象时,会按正确顺序调用子类→父类的析构函数,确保所有层级的资源都被释放。
- 你给
A添加virtual ~A() = default;,同时给B的析构函数加上override关键字的写法非常规范——override能确保你确实重写了父类的虚析构,避免拼写错误导致的意外问题。 - 这段代码中
make_unique<B>(b)是在堆上构造了一个B对象(拷贝自栈上的b),unique_ptr<A>指向这个B对象。当ptr超出作用域时,会先调用B的析构函数,再调用A的析构函数,完全释放B对象占用的所有内存,不会产生内存泄漏。
补充建议
- 如果要在容器中存储多态对象,推荐使用
vector<unique_ptr<A>>而非裸指针,容器销毁时会自动释放所有元素的内存,无需手动管理。 - 永远避免直接用父类类型构造子类对象,这种操作会触发对象切割,丢失子类特性,也无法实现多态。
内容的提问来源于stack exchange,提问作者Different
相关产品推荐
相关产品推荐

