编程C++ 后端开发者

描述 C++ 中的内存控制机制。new/delete 和智能指针之间有什么区别,为什么更倾向于使用智能指针?

用 Hintsage AI 助手通过面试

答案。

在 C++ 中,内存管理是通过明确的运算符 newdelete 来实现的,这些运算符动态地分配和释放内存。然而,在手动管理中,容易出现内存泄漏或双重删除。

随着 C++11 标准的出现,引入了智能指针,如 std::unique_ptrstd::shared_ptrstd::weak_ptr。它们自动管理对象的生命周期,并在超出作用域时保证资源的释放,即使在发生异常的情况下也是如此。

比较示例:

// 手动释放内存 Foo* ptr = new Foo(); // ... delete ptr; // 使用智能指针更安全 std::unique_ptr<Foo> ptr2 = std::make_unique<Foo>(); // 不需要 delete — 一切由 unique_ptr 来处理

智能指针减少了内存泄漏的风险,使代码更安全和可读。

陷阱问题。

如果对同一个指针调用 delete 两次,会发生什么?

答案: 第一次调用 delete 后,内存已经被释放。再次调用将导致未定义行为(undefined behavior)。示例:

Foo* p = new Foo(); delete p; delete p; // 错误!

为避免此情况,在释放后将指针设为 nullptr:

delete p; p = nullptr;

因不了解该主题的细微差别而导致的实际错误示例。


故事

在一个大型 C++ 项目中,开发者手动通过 delete 释放动态内存,忘记在几条函数异常出口时删除指针。这导致了内存泄漏,只有在负载测试中才被发现。


故事

在不同代码部分之间尝试共享原始指针,导致出现双重内存清理 — 某些代码部分执行 delete,而未通知其他部分。结果:生产中的段错误,核心转储分析立即显示了原因。


故事

在将旧项目迁移到新的 C++ 标准后,保留了部分使用原始指针的代码,而新类已经使用智能指针。遇到了资源所有权转移的错误:内存被“两次”释放 — 首先手动释放,然后智能指针的析构函数自动释放。