背景:
普通(原始)指针是 C++ 中处理动态内存的传统机制。这是一种通用的抽象机制,但遗憾的是,很容易出错:内存泄漏、双重删除、悬挂指针错误。因此,自 C++11 起,标准库引入了智能指针——模板类(std::unique_ptr、std::shared_ptr、std::weak_ptr),它们自动管理对象的生命周期。
问题:
在使用普通指针时,内存的分配和释放责任在于程序员。释放内存中的错误会导致内存泄漏、数据损坏和程序崩溃。尤其在处理异常或将指针传递给其他函数时,情况会特别复杂。
解决方案:
智能指针封装了分配的内存,并在没有所有者时自动释放它。它们实现了 RAII。std::unique_ptr 提供独占所有权,std::shared_ptr 提供共享所有权,std::weak_ptr 提供非控制所有权(以防止“引用循环”)。
代码示例:
#include <memory> void foo() { std::unique_ptr<int> p = std::make_unique<int>(5); // 即使在异常情况下,内存也会被释放 // ... }
关键特性:
可以在通过 new[] 创建的数组中使用 std::unique_ptr 吗?
不行,数组应使用 std::unique_ptr<T[]>:这样会调用 delete[] 而不是 delete。
std::unique_ptr<int[]> arr(new int[10]);
标准智能指针能否防止所有可能的内存泄漏?
不行。例如,std::shared_ptr 之间的循环引用会导致内存泄漏。为打破这种循环,可以使用 std::weak_ptr。
智能指针能否“删除”同一对象两次?
不行,前提是不违反所有权逻辑(不使用原始指针!)。如果手动复制原始指针,则销毁可能会发生两次。
使用原始指针,手动释放内存,在抛出异常时不会释放内存。
优点:
缺点:
使用 std::unique_ptr 和 std::make_unique 创建对象并将其传递至函数。
优点:
缺点: