C++怎么使用智能指针数组_C++unique_ptr与shared_ptr管理数组【内存】

3次阅读

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

C++怎么使用智能指针数组_C++unique_ptr与shared_ptr管理数组【内存】

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()
  • 都不能用 sizeofstd::size 获取长度 —— 数组大小只存在分配时,智能指针本身不保存该信息

别把智能指针数组当 vector 用,边界检查和扩容是硬伤

它们只是带自动析构的裸数组封装,不是容器替代品。越界访问不会报错,扩容不存在,插入删除更无从谈起。

立即学习C++免费学习笔记(深入)”;

  • 没有 at() 方法,p[i] 完全不检查下标 —— 错了就是段错误或静默数据损坏
  • 无法动态增减长度;想“扩容”只能新建更大数组,手动 std::copy,再移交所有权
  • 如果需要长度、迭代器、异常安全的访问,直接用 std::vector;只有当你明确需要零成本抽象、且确定生命周期简单时,才考虑智能指针数组

数组维度信息彻底丢失这点最容易被忽略——传参时若只给 std::shared_ptr<int></int>,接收方根本不知道它指向多少个元素,得额外传一个 size_t 参数,否则就是埋雷。

text=ZqhQzanResources