在C++的动态内存管理场景中,数组的释放需要匹配delete[]操作符,若误用delete很容易引发未定义行为。unique_ptr作为独占所有权的智能指针,针对数组场景提供了专门的特化实现,能够很好地支持数组的生命周期管理。

unique_ptr数组特化的基本用法
unique_ptr对数组的特化通过模板参数指定,当模板第二个参数为默认删除器时,若第一个参数是数组类型,unique_ptr会自动使用delete[]作为释放逻辑。声明数组类型的unique_ptr时,需要显式指定元素类型加方括号的形式。
#include <memory>
#include <iostream>
int main() {
// 声明管理int数组的unique_ptr,分配包含3个元素的数组
std::unique_ptr<int[]> arr_ptr(new int[3]{1, 2, 3});
// 通过[]运算符访问数组元素
for (int i = 0; i < 3; ++i) {
std::cout << arr_ptr[i] << std::endl;
}
// 离开作用域时自动调用delete[]释放数组内存
return 0;
}
普通unique_ptr与数组特化版本的差异
普通unique_ptr和数组特化版本的核心差异体现在释放逻辑和访问方式上,具体对比如下:
| 对比项 | 普通unique_ptr<T> | unique_ptr<T[]>数组特化版本 |
|---|---|---|
| 释放逻辑 | 调用delete释放单个对象 | 调用delete[]释放数组 |
| 元素访问方式 | 通过*解引用或->访问成员 | 通过[]运算符访问数组元素 |
| 模板参数要求 | 第一个参数为对象类型T | 第一个参数为数组类型T[] |
自定义删除器场景下的数组管理
如果数组的内存分配不是通过new[]完成,比如使用malloc或者自定义的内存分配函数,也可以为unique_ptr指定自定义删除器来支持数组管理。自定义删除器需要匹配数组的释放逻辑。
#include <memory>
#include <cstdlib>
#include <iostream>
// 自定义删除器,使用free释放malloc分配的数组
struct FreeDeleter {
void operator()(int* ptr) const {
if (ptr) {
free(ptr);
}
}
};
int main() {
// 使用malloc分配数组,绑定自定义删除器
std::unique_ptr<int, FreeDeleter> custom_arr_ptr(static_cast<int*>(malloc(sizeof(int) * 3)));
if (custom_arr_ptr) {
for (int i = 0; i < 3; ++i) {
custom_arr_ptr.get()[i] = i * 10;
}
for (int i = 0; i < 3; ++i) {
std::cout << custom_arr_ptr.get()[i] << std::endl;
}
}
return 0;
}
使用注意事项
- 不要将普通unique_ptr<T>用于管理数组,否则会导致释放时调用delete而非delete[],引发内存错误。
- 数组特化的unique_ptr不支持*解引用和->运算符,只能通过[]访问元素,若需要获取原始数组指针可以使用
get()方法。 - unique_ptr的数组特化版本不支持自动推导数组长度,使用时需要开发者自行维护数组的有效长度,避免越界访问。
- 若使用make_unique创建数组,C++14及以上版本支持
std::make_unique<int[]>(3)的形式,会默认初始化数组元素,比直接使用new更安全。
总结
unique_ptr通过数组特化版本完美支持了数组的管理需求,能够自动匹配delete[]释放逻辑,避免手动管理数组内存的遗漏问题。开发者在使用时只需要正确声明数组类型的unique_ptr,就可以像使用普通数组一样通过[]访问元素,同时享受智能指针带来的自动内存回收优势。在需要自定义内存分配逻辑的场景下,也可以通过绑定自定义删除器让unique_ptr适配不同的数组分配场景,灵活性较高。
unique_ptr智能指针数组管理RAII修改时间:2026-07-04 22:45:22