最安全方式是用 std::unique_ptr 管理动态数组,构造时传 new int[5],转移用 std::move(),原指针变 nullptr,析构自动调用 delete[]。

用 std::unique_ptr 转移动态数组所有权最安全
直接用裸指针(如 int*)做“所有权转移”没有语言保障,本质只是复制地址,极易导致双重释放或内存泄漏。C++11 起,标准做法是用 std::unique_ptr 管理动态数组,它天然支持移动语义,能真正把所有权从一个变量转移到另一个。
关键点:必须用数组特化版本 std::unique_ptr<t></t>,不能用默认的 std::unique_ptr<t></t>,否则析构时调用 delete 而非 delete[],引发未定义行为。
-
std::unique_ptr<int></int>构造时传入new int[5],析构自动调用delete[] - 转移用
std::move():原指针变为空(nullptr),新指针接管内存和析构责任 - 转移后对原指针解引用或释放会触发断言或崩溃,这是设计意图——防止误用
std::unique_ptr<int> a(new int[3]{1,2,3});
std::unique_ptr<int> b = std::move(a); // a 现在为 nullptr
// assert(!a); // 正确:a 已放弃所有权
// std::cout <h3>为什么不用 <code>std::shared_ptr</code>?</h3>
<p>如果目标只是“转移”,而非“共享”,<code>std::shared_ptr</code> 是过度设计。它引入引用计数开销,且允许多个指针同时持有同一块内存,违背“单一所有权转移”的原始意图。</p>
<p>但若后续需要多处访问、生命周期不确定,<code>std::shared_ptr</code> 才合适——此时不是“转移”,而是“共享”:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2659" title="C++"><img
src="https://img.php.cn/upload/skill/000/000/081/178927213426672.jpg" alt="C++" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill2659" title="C++" class="overflowclass">C++</a>
<p class="overflowclass">"空空如也"</p>
</div>
<a rel="nofollow" href="/xiazai/skill2659" title="C++" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>
<code>std::shared_ptr<int></int></code> 也需显式指定数组类型,否则析构错误</li>
<li>赋值或拷贝即增加引用计数,无需 <code>std::move</code>
</li>
<li>所有副本都失效后才调用 <code>delete[]</code>
</li>
</ul>
<pre class="brush:php;toolbar:false;">std::shared_ptr<int> x(new int[2]{4,5});
std::shared_ptr<int> y = x; // x 和 y 共享所有权,引用计数=2</int></int>
裸指针强行“模拟转移”的风险
有人会写 int* b = a; a = nullptr;,这看起来像转移,但完全绕过类型系统和 RAII,属于高危操作。
- 编译器无法检查是否遗漏置空,
a后续被意外释放会导致双重delete[] - 函数传参时无法表达“我将交出所有权”,调用方无法感知责任变更
- 异常安全为零:若
a = nullptr前发生异常,a仍持有内存,但无人负责释放 - 不兼容容器(如
std::vector<:unique_ptr>></:unique_ptr>),而智能指针可直接存入
数组大小信息丢失问题
std::unique_ptr<t></t> 不存储长度,就像裸 T* 一样。如果你需要“带长度的数组所有权”,得额外维护 size:
- 封装成结构体:
struct owned_int_array { std::unique_ptr<int> ptr; size_t size; };</int> - 改用
std::vector<t></t>:它自带 size()、自动扩容、异常安全,多数场景下比手动管理数组更合适 - 避免用
std::make_unique<t>(n)</t>创建后立刻丢掉 size——除非你真不需要它
所有权转移本身不解决尺寸管理,那是业务逻辑层的责任。别指望指针类型替你记住数组多长。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










