最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
C++怎样使用std::unique_ptr管理动态分配的数组
时间:2026-06-23 08:28:47 编辑:袖梨 来源:一聚教程网
<p>std::unique_ptr<T[]> 必须显式指定数组类型,否则 new int[10] 会调用 delete 而非 delete[],导致未定义行为;它支持 operator[] 但禁用 operator* 和 operator->,构造需 new T[N] 或 C++14+ 的 make_unique<N>()。</p>
std::unique_ptr 必须显式指定数组类型
直接用 std::unique_ptr<int></int> 管理 new int[10] 会导致析构时调用 delete 而非 delete[],引发未定义行为——这是最常踩的坑。
正确做法是使用带方括号的特化类型:std::unique_ptr<int></int>。编译器据此选择 delete[],并禁用 operator* 和 operator->(因为数组不支持解引用单个对象)。
-
std::unique_ptr<int></int>支持operator[],可像原生数组一样访问元素 - 不能写成
std::unique_ptr<int></int>—— 编译器不接受带长度的数组类型作为模板参数 - 构造时只能传入
new int[N],不能传入栈数组地址或空指针(除非显式初始化为nullptr)
初始化方式:用 new T[N],别用 make_unique(C++14 之前不支持数组)
std::make_unique 在 C++14 才开始支持数组,且语法和语义与标量不同:它会自动推导 T[] 类型,但不接受自定义大小参数(即不能写 make_unique<int>(10)</int>)。
因此在 C++11 或需要明确控制内存分配逻辑时,必须手写 new:
立即学习“C++免费学习笔记(深入)”;
std::unique_ptr<int[]> ptr(new int[5]);
C++14+ 可安全使用:
auto ptr = std::make_unique<int[]>(5); // 分配 5 个默认初始化的 int
-
make_unique<int>(N)</int>总是值初始化(int()→ 0),而new int[N]是默认初始化(值未定义) - 若需保留未初始化行为(如后续 memcpy),只能用
new+std::unique_ptr<t></t> - 无法用
make_unique构造非默认可构造类型的数组(如std::unique_ptr<:string></:string>会调用每个元素的默认构造函数)
移动语义可用,但拷贝被禁用
std::unique_ptr<t></t> 遵循唯一所有权原则,拷贝构造和赋值运算符被显式删除;移动则完全支持,且移动后源对象变为 nullptr。
- 移动后原指针失效,再次访问
ptr.get()返回nullptr,调用operator[]会触发空指针解引用 - 可安全用于容器:例如
std::vector<:unique_ptr>></:unique_ptr>存储变长数组 - 函数返回时推荐直接移动:
return std::move(ptr);(虽然命名变量返回时通常自动移动,但显式写出更清晰)
释放时机与资源泄漏风险点
数组版 unique_ptr 在超出作用域、被移动、或显式调用 reset() 时自动调用 delete[],但有三个容易忽略的边界情况:
- 若在构造时抛出异常(比如
new失败),unique_ptr不会持有任何资源,无需担心泄漏 - 若用
release()交出裸指针,必须手动确保后续调用delete[],否则泄漏 - 不能混用
get()返回的指针和其它智能指针(如再包一层shared_ptr),否则双重释放
真正难排查的是跨 DLL 边界传递:若 new 和 delete[] 不在同一个模块(尤其 Windows 上不同 CRT 实例),即使类型匹配也会崩溃。这时要么统一用 make_unique(保证分配/释放同源),要么改用 std::vector。
相关文章
- steam上传视频教程 06-23
- 布袋鼠小说app如何进行阅读 06-23
- 快手极速版官方App网页版在哪下载 06-23
- 我的世界2026秒玩入口网址是什么 06-23
- 空洞骑士丝之歌全部五个结局攻略 丝之歌结局达成条件 06-23
- 崩坏3 8.7新春版本福利一览 06-23