std::unique_ptr管理数组必须加[]否则析构错误;c++17前shared_ptr管数组需自定义删除器,之后原生支持;二者operator[]可访问但无边界检查、不存长度信息,不可替代vector。

std::unique_ptr 必须带方括号才能正确析构数组
不加 [] 的 std::unique_ptr<int></int> 管理单个 int,但想管数组就得显式写成 std::unique_ptr<int></int>。否则 delete 会调用非数组版本,只析构第一个元素,其余内存泄漏且行为未定义。
- 错误写法:
std::unique_ptr<int> p(new int[10]);</int>—— 编译通过,运行时 UB - 正确写法:
std::unique_ptr<int> p(new int[10]);</int>—— 析构时自动调用delete[] - 初始化推荐用
std::make_unique<int>(n)</int>,避免裸new;但注意std::make_unique不支持带初始化列表的数组(如make_unique<int>({1,2,3})</int>无效)
std::shared_ptr 从 C++17 起才原生支持数组类型
旧标准下用 std::shared_ptr<int></int> 管数组必须手动传自定义删除器,否则照样崩。C++17 加了模板特化,std::shared_ptr<int></int> 才真正安全可用。
- C++14 及以前:
std::shared_ptr<int> p(new int[5], [](int* ptr) { delete[] ptr; });</int> - C++17+:
std::shared_ptr<int> p(new int[5]);</int>—— 删除器自动为delete[] - 别用
std::make_shared<int>(n)</int>:它不合法,因为make_shared内部用的是new(非new[]),目前所有标准都禁止该用法
unique_ptr 和 shared_ptr 的 operator[] 行为一致但语义不同
两者都重载了 operator[],能像原生数组一样用 p[i] 访问,但背后资源管理模型完全不同。
-
std::unique_ptr<int></int>:独占所有权,不可拷贝,移动后原指针变空;适合生命周期明确、无需共享的场景(如函数内临时缓冲区) -
std::shared_ptr<int></int>:引用计数,可拷贝共享;但每次拷贝有原子操作开销,且数组长度信息完全丢失(无法像std::vector那样查size()) - 都不能用
sizeof或std::size获取长度 —— 数组大小只存在分配时,智能指针本身不保存该信息
别把智能指针数组当 vector 用,边界检查和扩容是硬伤
它们只是带自动析构的裸数组封装,不是容器替代品。越界访问不会报错,扩容不存在,插入删除更无从谈起。
立即学习“C++免费学习笔记(深入)”;
- 没有
at()方法,p[i]完全不检查下标 —— 错了就是段错误或静默数据损坏 - 无法动态增减长度;想“扩容”只能新建更大数组,手动
std::copy,再移交所有权 - 如果需要长度、迭代器、异常安全的访问,直接用
std::vector;只有当你明确需要零成本抽象、且确定生命周期简单时,才考虑智能指针数组
数组维度信息彻底丢失这点最容易被忽略——传参时若只给 std::shared_ptr<int></int>,接收方根本不知道它指向多少个元素,得额外传一个 size_t 参数,否则就是埋雷。










