文章目录

C++ 内存管理:new/delete 与智能指针

发布于 2026-04-03 03:00:12 · 浏览 10 次 · 评论 0 条

C++ 内存管理:new/delete 与智能指针

C++ 允许程序员直接控制内存,这是它高效灵活的关键,但也容易引发内存泄漏、重复释放等严重问题。掌握 new/delete 和现代智能指针的正确用法,是写出安全可靠 C++ 代码的基础。


理解原始内存操作:new 与 delete

使用 new 动态分配对象时,程序会在堆(heap)上创建一个对象,并返回指向它的指针。例如:

int* p = new int(42);

这行代码在堆上分配了一个 int 类型的空间,并用值 42 初始化它,p 指向该地址。

必须成对使用 delete 释放内存。当你不再需要该对象时,调用 delete

delete p;

忘记调用 delete 会导致内存泄漏——程序占用的内存不断增加,最终可能耗尽系统资源。

特别注意数组情况:如果你用 new[] 分配数组,必须用 delete[] 释放

int* arr = new int[10];
// ... 使用 arr ...
delete[] arr;  // 错误写法:delete arr; 会导致未定义行为

使用原始 new/delete 的主要风险在于:

  • 忘记释放(内存泄漏)
  • 多次释放同一指针(重复释放)
  • 异常抛出导致 delete 未执行(异常安全问题)

用智能指针自动管理内存

C++11 引入了智能指针,它们利用“资源获取即初始化”(RAII)技术,在对象生命周期结束时自动释放内存,彻底避免手动管理错误。

第一步:优先使用 std::unique_ptr

包含头文件 <memory>,然后声明 std::unique_ptr

#include <memory>

std::unique_ptr<int> ptr = std::make_unique<int>(42);

std::unique_ptr 表示“独占所有权”——同一时间只能有一个 unique_ptr 指向该对象。当 ptr 离开作用域(如函数返回),其析构函数会自动调用 delete

不要使用裸 new 创建智能指针始终用 std::make_unique

// 正确
auto ptr = std::make

// 错误(不推荐)
std::unique_ptr<int> ptr(new int(42));

后者在复杂表达式中可能因异常导致内存泄漏,而 make_unique 是异常安全的。

第二步:需要共享时使用 std::shared_ptr

当多个对象需要共享同一个资源时,使用 std::shared_ptr

auto shared = std::make_shared<int>(42);
auto another = shared;  // 引用计数变为 2

std::shared_ptr 内部维护一个引用计数。每当有新的 shared_ptr 指向同一对象,计数加一;当某个 shared_ptr 被销毁,计数减一。当计数归零时,自动释放内存

同样,优先使用 std::make_shared 而非裸 new,原因同上。

第三步:配合 std::weak_ptr 打破循环引用

std::shared_ptr 的一个陷阱是循环引用:A 持有 B 的 shared_ptr,B 又持有 A 的 shared_ptr,导致引用计数永远不为零,内存无法释放。

引入 std::weak_ptr 解决此问题。它不增加引用计数,仅“观察”对象是否存在:

class Child;
class Parent {
public:
    std::shared_ptr<Child> child;
};

class Child {
public:
    std::weak_ptr<Parent> parent;  // 使用 weak_ptr 避免循环
};

检查 weak_ptr 是否有效需先调用 lock()

if (auto p = child->parent.lock()) {
    // p 是 shared_ptr,可安全使用
}

如何选择正确的工具

下表总结了不同场景下的推荐选择:

场景 推荐方式 原因
对象生命周期明确,仅一处使用 std::unique_ptr 零开销,自动释放,防止拷贝
多个所有者共享同一对象 std::shared_ptr 自动引用计数管理
需要观察对象但不参与所有权 std::weak_ptr 避免循环引用,不阻止销毁
性能极度敏感且能保证安全 裸指针 + 手动 new/delete 仅限底层库或特殊优化,普通代码禁用

实战建议:彻底告别裸 new/delete

  1. 禁止在应用层代码中直接使用 new delete。所有动态内存应通过智能指针管理。
  2. 函数参数和返回值优先使用智能指针。例如,返回新对象时返回 std::unique_ptr<T>,表明调用者获得所有权。
  3. 容器中存储智能指针而非裸指针。如 std::vector<std::unique_ptr<Base>> 可安全管理多态对象集合。
  4. 警惕隐式转换shared_ptr 可隐式转换为 bool,但 weak_ptr 不行,需显式调用 expired()lock()
// 安全的工厂函数示例
std::unique_ptr<Widget> createWidget(int type) {
    if (type == 1) {
        return std::make_unique<ConcreteWidgetA>();
    }
    return std::make_unique<ConcreteWidgetB>();
}

遵循这些规则,你的 C++ 程序将几乎不可能出现内存泄漏或双重释放错误。智能指针不是“高级特性”,而是现代 C++ 内存管理的标准实践。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文