C++中shared_ptr与对象数组结合使用的问题
先给你明确拆解问题的答案:
1. shared_ptr<A> c(new A[5])确实会导致内存泄漏
当你用new A[5]分配数组时,堆上会开辟容纳5个A对象的连续内存,同时调用每个A的构造函数。但std::shared_ptr的默认删除器用的是delete而非delete[]——delete只会销毁第一个A对象(调用它的析构函数),仅释放该对象的内存,剩下4个A的析构函数不会被触发,它们占用的内存也无法回收,最终造成内存泄漏。
2. C17和C20中的情况
- C++17之前,
std::shared_ptr没有原生支持数组类型,直接写shared_ptr<A>(new A[5])的话,默认删除器依然是delete,泄漏问题依然存在。 - C++17引入了
std::shared_ptr<T[]>的特化版本,如果你把代码改成:
此时shared_ptr<A[]> c(new A[5]);shared_ptr的默认删除器会自动使用delete[],正确销毁所有5个A对象并释放整个数组的内存,不会有泄漏。 - C++20不仅保留了这个特化,还支持用
std::make_shared直接创建数组类型的shared_ptr,比如:
这种写法更安全,避免了手动auto c = make_shared<A[]>(5);new的风险,同时自动处理数组的正确释放。
3. 自定义删除器的解决方案
如果受限于旧标准无法用shared_ptr<T[]>,你可以像代码里计划的那样传入自定义删除器:
shared_ptr<A> d(new A[5], [](A* ptr){ delete[] ptr; });
这个lambda删除器会在shared_ptr引用计数归零时,调用delete[] ptr,从而正确销毁数组中所有对象并释放全部内存。
最佳实践
- C17及以后,优先用
shared_ptr<T[]>特化版本,或者C20的make_shared<T[]>,它们自动处理数组释放逻辑,不用手动写删除器。 - 尽量避免直接用
new初始化shared_ptr,无论是单个对象还是数组,make_shared系列是更安全的选择,能减少泄漏风险,还能优化内存分配。
内容的提问来源于stack exchange,提问作者Hasan Zeen
相关产品推荐
相关产品推荐

