413 lines
37 KiB
HTML
413 lines
37 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh" dir="ltr" class="client-nojs" xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh">
|
|
<head><meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<title>std::unique_ptr</title>
|
|
<link rel="stylesheet" href="ext.css" />
|
|
<link rel="stylesheet" href="site_modules.css" />
|
|
</head>
|
|
<body class="mediawiki ltr sitedir-ltr ns-0 ns-subject page-cpp_memory_unique_ptr skin-cppreference2 action-view cpp-navbar">
|
|
<div id="cpp-content-base">
|
|
<div id="content"><a id="top"></a>
|
|
<h1 id="firstHeading" class="firstHeading"><span style="font-size:0.7em; line-height:130%">std::</span>unique_ptr</h1>
|
|
<div id="bodyContent">
|
|
<div id="contentSub"><span class="subpages">< <a href="cpp.html">cpp</a>‎ | <a href="cpp-memory.html">memory</a></span></div>
|
|
<div id="mw-content-text" lang="zh" dir="ltr" class="mw-content-ltr" xml:lang="zh">
|
|
<table class="t-dcl-begin">
|
|
<tbody>
|
|
<tr class="t-dsc-header">
|
|
<td>
|
|
<div>定义于头文件 <code><a href="cpp-header-memory.html"><memory></a></code></div>
|
|
</td>
|
|
<td></td>
|
|
<td></td>
|
|
</tr>
|
|
<tr class="t-dcl t-since-cxx11">
|
|
<td>
|
|
<div><span class="mw-geshi cpp source-cpp"><span class="kw1">template</span><span class="sy1"><</span><br /></span>
|
|
<p> <span class="kw1">class</span> T,<br />
|
|
<span class="kw1">class</span> Deleter <span class="sy1">=</span> <a href="cpp-memory-default_delete.html"><span class="kw745">std::<span class="me2">default_delete</span></span></a><span class="sy1"><</span>T<span class="sy1">></span><br /></p>
|
|
<span class="sy1">></span> <span class="kw1">class</span> unique_ptr<span class="sy4">;</span></div>
|
|
</td>
|
|
<td>(1)</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
<tr class="t-dcl t-since-cxx11">
|
|
<td>
|
|
<div><span class="mw-geshi cpp source-cpp"><span class="kw1">template</span> <span class="sy1"><</span><br /></span>
|
|
<p> <span class="kw1">class</span> T,<br />
|
|
<span class="kw1">class</span> Deleter<br /></p>
|
|
<span class="sy1">></span> <span class="kw1">class</span> unique_ptr<span class="sy1"><</span>T<span class="br0">[</span><span class="br0">]</span>, Deleter<span class="sy1">></span><span class="sy4">;</span></div>
|
|
</td>
|
|
<td>(2)</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
<tr class="t-dcl-sep">
|
|
<td></td>
|
|
<td></td>
|
|
<td></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p><code>std::unique_ptr</code> 是通过指针占有并管理另一对象,并在 <code>unique_ptr</code> 离开作用域时释放该对象的智能指针。</p>
|
|
<p>在下列两者之一发生时用关联的删除器释放对象:</p>
|
|
<ul>
|
|
<li>销毁了管理的 <code>unique_ptr</code> 对象</li>
|
|
<li>通过 <span class="t-lc"><a href="cpp-memory-unique_ptr-operator=.html">operator=</a></span> 或 <span class="t-lc"><a href="cpp-memory-unique_ptr-reset.html">reset()</a></span> 赋值另一指针给管理的 <code>unique_ptr</code> 对象。</li>
|
|
</ul>
|
|
<p>通过调用 <span class="t-c"><span class="mw-geshi cpp source-cpp">get_deleter<span class="br0">(</span><span class="br0">)</span><span class="br0">(</span>ptr<span class="br0">)</span></span></span> ,用潜在为用户提供的删除器释放对象。默认删除器用 <span class="t-c"><span class="mw-geshi cpp source-cpp">delete</span></span> 运算符,它销毁对象并解分配内存。</p>
|
|
<p><code>unique_ptr</code> 亦可以不占有对象,该情况下称它为<i>空 (empty)</i>。</p>
|
|
<p><code>std::unique_ptr</code> 有两个版本:</p>
|
|
<div class="t-li1"><span class="t-li">1)</span> 管理单个对象(例如以 <span class="t-c"><span class="mw-geshi cpp source-cpp">new</span></span> 分配)</div>
|
|
<div class="t-li1"><span class="t-li">2)</span> 管理动态分配的对象数组(例如以 <span class="t-c"><span class="mw-geshi cpp source-cpp">new<span class="br0">[</span><span class="br0">]</span></span></span> 分配)</div>
|
|
<p>类满足<a href="cpp-named_req-MoveConstructible.html"><span style="font-style:italic">可移动构造</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(MoveConstructible)</span></a> 和<a href="cpp-named_req-MoveAssignable.html"><span style="font-style:italic">可移动赋值</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(MoveAssignable)</span></a> 的要求,但不满足<a href="cpp-named_req-CopyConstructible.html"><span style="font-style:italic">可复制构造</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(CopyConstructible)</span></a> 或<a href="cpp-named_req-CopyAssignable.html"><span style="font-style:italic">可复制赋值</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(CopyAssignable)</span></a> 的要求。</p>
|
|
<table class="t-par-begin">
|
|
<tr class="t-par-hitem">
|
|
<td colspan="3">类型要求</td>
|
|
</tr>
|
|
<tr class="t-par-req">
|
|
<td colspan="3">-
|
|
<div class="spacer"></div>
|
|
<code>Deleter</code> 必须是<a href="cpp-named_req-FunctionObject.html"><span style="font-style:italic">函数对象</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(FunctionObject)</span></a> 或到<a href="cpp-named_req-FunctionObject.html"><span style="font-style:italic">函数对象</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(FunctionObject)</span></a> 的左值引用或到函数的左值引用,可以 <code>unique_ptr<T, Deleter>::pointer</code> 类型参数调用</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E6.B3.A8.E8.A7.A3">注解</span></h3>
|
|
<p>只有非 const 的 <code>unique_ptr</code> 能转移被管理对象的所有权给另一 <code>unique_ptr</code> 。若对象的生存期为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> std<span class="sy4">::</span><span class="me2">unique_ptr</span></span></span> 所管理,则它被限定在创建指针的作用域中。</p>
|
|
<p><code>std::unique_ptr</code> 常用于管理对象的生存期,包含:</p>
|
|
<ul>
|
|
<li>通过正常退出和经由异常退出两者上的受保证删除,提供异常安全,给处理拥有动态生存期的对象的类和函数</li>
|
|
</ul>
|
|
<ul>
|
|
<li>传递独占的拥有动态生存期的对象的所有权到函数</li>
|
|
</ul>
|
|
<ul>
|
|
<li>从函数获得独占的拥有动态生存期对象的所有权</li>
|
|
</ul>
|
|
<ul>
|
|
<li>作为具移动容器的元素类型,例如保有指向动态分配对象的指针的 <span class="t-lc"><a href="cpp-container-vector.html">std::vector</a></span> (例如,若想要多态行为)</li>
|
|
</ul>
|
|
<p><code>std::unique_ptr</code> 可为<a href="cpp-language-type.html#.E4.B8.8D.E5.AE.8C.E6.95.B4.E7.B1.BB.E5.9E.8B">不完整类型</a> <code>T</code> 构造,例如用于改善用作 <a href="cpp-language-pimpl.html">pImpl 手法</a>中柄的用途。若使用默认删除器,则 <code>T</code> 必须在代码中调用删除器点处完整,这发生于析构函数、移动赋值运算符和 <code>std::unique_ptr</code> 的 <code>reset</code> 成员函数中。(相反地, <span class="t-lc"><a href="cpp-memory-shared_ptr.html">std::shared_ptr</a></span> 不能从指向不完整类型的裸指针构造,但可于 <code>T</code> 不完整处销毁)。注意若 <code>T</code> 是类模板特化,则以 <code>unique_ptr</code> 为运算数的使用,如 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy3">!</span>p</span></span> ,因 <a href="cpp-language-adl.html">ADL</a> 而要求 <code>T</code> 的形参完整。</p>
|
|
<p>若 <code>T</code> 是某基类 <code>B</code> 的<a href="cpp-language-derived_class.html">派生类</a>,则 <span class="t-c"><span class="mw-geshi cpp source-cpp">std<span class="sy4">::</span><span class="me2">unique_ptr</span><span class="sy1"><</span>T<span class="sy1">></span></span></span> <a href="cpp-memory-unique_ptr-unique_ptr.html">可隐式转换</a>为 <span class="t-c"><span class="mw-geshi cpp source-cpp">std<span class="sy4">::</span><span class="me2">unique_ptr</span><span class="sy1"><</span>B<span class="sy1">></span></span></span>。产生的 <span class="t-c"><span class="mw-geshi cpp source-cpp">std<span class="sy4">::</span><span class="me2">unique_ptr</span><span class="sy1"><</span>B<span class="sy1">></span></span></span> 的默认删除器将使用 <code>B</code> 的 <a href="cpp-memory-new-operator_delete.html">operator delete</a> ,这导致<a href="cpp-language-destructor.html#.E8.99.9A.E6.9E.90.E6.9E.84.E5.87.BD.E6.95.B0">未定义行为</a>,除非 <code>B</code> 的析构函数为<a href="cpp-language-virtual.html">虚</a>。注意 <span class="t-lc"><a href="cpp-memory-shared_ptr.html">std::shared_ptr</a></span> 表现有别: <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-memory-shared_ptr.html"><span class="kw733">std::<span class="me2">shared_ptr</span></span></a><span class="sy1"><</span>B<span class="sy1">></span></span></span> 将使用类型 <code>T</code> 的 <a href="cpp-memory-new-operator_delete.html">operator delete</a> ,而且即使 <code>B</code> 的析构函数非<a href="cpp-language-virtual.html">虚</a>,也会正确删除被占有对象。</p>
|
|
<p>不同于 <span class="t-lc"><a href="cpp-memory-shared_ptr.html">std::shared_ptr</a></span> , <code>std::unique_ptr</code> 可通过任何满足<a href="cpp-named_req-NullablePointer.html"><span style="font-style:italic">可空指针</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(NullablePointer)</span></a> 的定制柄类型管理对象。例如,这允许管理位于共享内存,但提供定义 <code>typedef <a rel="nofollow" class="external text" href="http://www.boost.org/doc/libs/release/doc/html/boost/interprocess/offset_ptr.html">boost::offset_ptr</a> pointer;</code> 或其他<a href="cpp-named_req-Allocator.html#.E7.BC.80.E9.A5.B0.E6.8C.87.E9.92.88">缀饰指针</a>的 <code>Deleter</code> 的对象。</p>
|
|
<h3><span class="mw-headline" id=".E6.88.90.E5.91.98.E7.B1.BB.E5.9E.8B">成员类型</span></h3>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc-hitem">
|
|
<td>成员类型</td>
|
|
<td>定义</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">pointer</span></span></td>
|
|
<td>若该类型存在则为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-types-remove_reference.html"><span class="kw606">std::<span class="me2">remove_reference</span></span></a><span class="sy1"><</span>Deleter<span class="sy1">></span><span class="sy4">::</span><span class="me2">type</span><span class="sy4">::</span><span class="me2">pointer</span></span></span> ,否则为 <code>T*</code> 。必须满足<a href="cpp-named_req-NullablePointer.html"><span style="font-style:italic">可空指针</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(NullablePointer)</span></a> 。</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">element_type</span></span></td>
|
|
<td><code>T</code> ,此 <code>unique_ptr</code> 所管理的对象类型</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">deleter_type</span></span></td>
|
|
<td><code>Deleter</code> ,函数对象或到函数或到函数对象的左值引用,会从析构函数调用</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E6.88.90.E5.91.98.E5.87.BD.E6.95.B0">成员函数</span></h3>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div t-dsc-member-nobold-div">
|
|
<div><a href="cpp-memory-unique_ptr-unique_ptr.html"><span class="t-lines"><span>(构造函数)</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>构造新的<code>unique_ptr</code><br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div t-dsc-member-nobold-div">
|
|
<div><a href="cpp-memory-unique_ptr-~unique_ptr.html"><span class="t-lines"><span>(析构函数)</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>析构所管理的对象,如果存在的话<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-operator=.html"><span class="t-lines"><span>operator=</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>为<code>unique_ptr</code>赋值<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2">
|
|
<h5><span class="mw-headline" id=".E4.BF.AE.E6.94.B9.E5.99.A8">修改器</span></h5>
|
|
</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-release.html"><span class="t-lines"><span>release</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>返回一个指向被管理对象的指针,并释放所有权<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-reset.html"><span class="t-lines"><span>reset</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>替换被管理对象<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-swap.html"><span class="t-lines"><span>swap</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>交换被管理对象<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2">
|
|
<h5><span class="mw-headline" id=".E8.A7.82.E5.AF.9F.E5.99.A8">观察器</span></h5>
|
|
</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-get.html"><span class="t-lines"><span>get</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>返回指向被管理对象的指针<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-get_deleter.html"><span class="t-lines"><span>get_deleter</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>返回用于析构被管理对象的删除器<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-operator_bool.html"><span class="t-lines"><span>operator bool</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>检查是否有关联的被管理对象<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2">
|
|
<h5><span class="mw-headline" id=".E5.8D.95.E5.AF.B9.E8.B1.A1.E7.89.88.E6.9C.AC.EF.BC.8C_unique_ptr.3CT.3E">单对象版本, <code>unique_ptr<T></code></span></h5>
|
|
</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-operator*.html"><span class="t-lines"><span>operator*</span><span>operator-></span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>解引用指向被管理对象的指针<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2">
|
|
<h5><span class="mw-headline" id=".E6.95.B0.E7.BB.84.E7.89.88.E6.9C.AC.EF.BC.8C_unique_ptr.3CT.5B.5D.3E">数组版本, <code>unique_ptr<T[]></code></span></h5>
|
|
</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-operator_at.html"><span class="t-lines"><span>operator[]</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>提供到被管理数组的有索引访问<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E9.9D.9E.E6.88.90.E5.91.98.E5.87.BD.E6.95.B0">非成员函数</span></h3>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-make_unique.html"><span class="t-lines"><span>make_unique</span><span>make_unique_for_overwrite</span></span></a></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx14">(C++14)</span></span><span><span class="t-mark-rev t-since-cxx20">(C++20)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>创建管理一个新对象的独占指针<br />
|
|
<span class="t-mark">(函数模板)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-operator_cmp.html"><span class="t-lines"><span>operator==</span><span>operator!=</span><span>operator<</span><span>operator<=</span><span>operator></span><span>operator>=</span><span>operator<=></span></span></a></div>
|
|
<div><span class="t-lines"><span></span><span><span class="t-mark-rev t-until-cxx20">(C++20 中移除)</span></span><span></span><span></span><span></span><span></span><span><span class="t-mark-rev t-since-cxx20">(C++20)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>与另一个 <code>unique_ptr</code> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp">nullptr</span></span> 进行比较<br />
|
|
<span class="t-mark">(函数模板)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-operator_ltlt.html"><span class="t-lines"><span>operator<<</span></span></a></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx20">(C++20)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>输出被管理指针的值到输出流<br />
|
|
<span class="t-mark">(函数模板)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-swap2.html"><span class="t-lines"><span>std::swap<span class="t-dsc-small">(std::unique_ptr)</span></span></span></a></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>特化 <span class="t-lc"><a href="cpp-algorithm-swap.html">std::swap</a></span> 算法<br />
|
|
<span class="t-mark">(函数模板)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E8.BE.85.E5.8A.A9.E7.B1.BB">辅助类</span></h3>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-memory-unique_ptr-hash.html"><span class="t-lines"><span>std::hash<span class="t-dsc-small"><std::unique_ptr></span></span></span></a></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td><span class="t-lc"><strong class="selflink">std::unique_ptr</strong></span> 的散列支持<br />
|
|
<span class="t-mark">(类模板特化)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E7.A4.BA.E4.BE.8B">示例</span></h3>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#include <iostream></span>
|
|
<span class="co2">#include <vector></span>
|
|
<span class="co2">#include <memory></span>
|
|
<span class="co2">#include <cstdio></span>
|
|
<span class="co2">#include <fstream></span>
|
|
<span class="co2">#include <cassert></span>
|
|
<span class="co2">#include <functional></span>
|
|
|
|
<span class="kw1">struct</span> B <span class="br0">{</span>
|
|
<span class="kw1">virtual</span> <span class="kw4">void</span> bar<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"B::bar<span class="es1">\n</span>"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="kw1">virtual</span> ~B<span class="br0">(</span><span class="br0">)</span> <span class="sy1">=</span> <span class="kw1">default</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">struct</span> D <span class="sy4">:</span> B
|
|
<span class="br0">{</span>
|
|
D<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"D::D<span class="es1">\n</span>"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
~D<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"D::~D<span class="es1">\n</span>"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="kw4">void</span> bar<span class="br0">(</span><span class="br0">)</span> override <span class="br0">{</span> <a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"D::bar<span class="es1">\n</span>"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 消费 unique_ptr 的函数能以值或以右值引用接收它</span>
|
|
std<span class="sy4">::</span><span class="me2">unique_ptr</span><span class="sy1"><</span>D<span class="sy1">></span> pass_through<span class="br0">(</span>std<span class="sy4">::</span><span class="me2">unique_ptr</span><span class="sy1"><</span>D<span class="sy1">></span> p<span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
p<span class="sy2">-</span><span class="sy1">></span>bar<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="kw1">return</span> p<span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="kw4">void</span> close_file<span class="br0">(</span><a href="cpp-io-c.html"><span class="kw1876">std::<span class="me2">FILE</span></span></a><span class="sy2">*</span> fp<span class="br0">)</span> <span class="br0">{</span> <a href="cpp-io-c-fclose.html"><span class="kw1815">std::<span class="me2">fclose</span></span></a><span class="br0">(</span>fp<span class="br0">)</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"unique ownership semantics demo<span class="es1">\n</span>"</span><span class="sy4">;</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw4">auto</span> p <span class="sy1">=</span> <a href="cpp-memory-unique_ptr-make_unique.html"><span class="kw734">std::<span class="me2">make_unique</span></span></a><span class="sy1"><</span>D<span class="sy1">></span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// p 是占有 D 的 unique_ptr</span>
|
|
<span class="kw4">auto</span> q <span class="sy1">=</span> pass_through<span class="br0">(</span>std<span class="sy4">::</span><span class="me2">move</span><span class="br0">(</span>p<span class="br0">)</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<a href="cpp-error-assert.html"><span class="kw773">assert</span></a><span class="br0">(</span><span class="sy3">!</span>p<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 现在 p 不占有任何内容并保有空指针</span>
|
|
q<span class="sy2">-</span><span class="sy1">></span>bar<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 而 q 占有 D 对象</span>
|
|
<span class="br0">}</span> <span class="co1">// ~D 调用于此</span>
|
|
|
|
<a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"Runtime polymorphism demo<span class="es1">\n</span>"</span><span class="sy4">;</span>
|
|
<span class="br0">{</span>
|
|
std<span class="sy4">::</span><span class="me2">unique_ptr</span><span class="sy1"><</span>B<span class="sy1">></span> p <span class="sy1">=</span> <a href="cpp-memory-unique_ptr-make_unique.html"><span class="kw734">std::<span class="me2">make_unique</span></span></a><span class="sy1"><</span>D<span class="sy1">></span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// p 是占有 D 的 unique_ptr</span>
|
|
<span class="co1">// 作为指向基类的指针</span>
|
|
p<span class="sy2">-</span><span class="sy1">></span>bar<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 虚派发</span>
|
|
|
|
<a href="cpp-container-vector.html"><span class="kw1268">std::<span class="me2">vector</span></span></a><span class="sy1"><</span>std<span class="sy4">::</span><span class="me2">unique_ptr</span><span class="sy1"><</span>B<span class="sy1">>></span> v<span class="sy4">;</span> <span class="co1">// unique_ptr 能存储于容器</span>
|
|
v.<span class="me1">push_back</span><span class="br0">(</span><a href="cpp-memory-unique_ptr-make_unique.html"><span class="kw734">std::<span class="me2">make_unique</span></span></a><span class="sy1"><</span>D<span class="sy1">></span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="sy4">;</span>
|
|
v.<span class="me1">push_back</span><span class="br0">(</span>std<span class="sy4">::</span><span class="me2">move</span><span class="br0">(</span>p<span class="br0">)</span><span class="br0">)</span><span class="sy4">;</span>
|
|
v.<span class="me1">emplace_back</span><span class="br0">(</span>new D<span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="kw1">for</span><span class="br0">(</span><span class="kw4">auto</span><span class="sy3">&</span> p<span class="sy4">:</span> v<span class="br0">)</span> p<span class="sy2">-</span><span class="sy1">></span>bar<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 虚派发</span>
|
|
<span class="br0">}</span> <span class="co1">// ~D called 3 times</span>
|
|
|
|
<a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"Custom deleter demo<span class="es1">\n</span>"</span><span class="sy4">;</span>
|
|
<a href="cpp-io-basic_ofstream.html"><span class="kw1732">std::<span class="me2">ofstream</span></span></a><span class="br0">(</span><span class="st0">"demo.txt"</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'x'</span><span class="sy4">;</span> <span class="co1">// 准备要读的文件</span>
|
|
<span class="br0">{</span>
|
|
std<span class="sy4">::</span><span class="me2">unique_ptr</span><span class="sy1"><</span><a href="cpp-io-c.html"><span class="kw1876">std::<span class="me2">FILE</span></span></a>, <span class="kw4">void</span> <span class="br0">(</span><span class="sy2">*</span><span class="br0">)</span><span class="br0">(</span><a href="cpp-io-c.html"><span class="kw1876">std::<span class="me2">FILE</span></span></a><span class="sy2">*</span><span class="br0">)</span> <span class="sy1">></span> fp<span class="br0">(</span><a href="cpp-io-c-fopen.html"><span class="kw1812">std::<span class="me2">fopen</span></span></a><span class="br0">(</span><span class="st0">"demo.txt"</span>, <span class="st0">"r"</span><span class="br0">)</span>,
|
|
close_file<span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="kw1">if</span><span class="br0">(</span>fp<span class="br0">)</span> <span class="co1">// fopen 可以打开失败;该情况下 fp 保有空指针</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="br0">(</span><span class="kw4">char</span><span class="br0">)</span><a href="cpp-io-c-fgetc.html"><span class="kw1820">std::<span class="me2">fgetc</span></span></a><span class="br0">(</span>fp.<span class="me1">get</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="br0">}</span> <span class="co1">// fclose() 调用于此,但仅若 FILE* 不是空指针</span>
|
|
<span class="co1">// (即 fopen 成功)</span>
|
|
|
|
<a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"Custom lambda-expression deleter demo<span class="es1">\n</span>"</span><span class="sy4">;</span>
|
|
<span class="br0">{</span>
|
|
std<span class="sy4">::</span><span class="me2">unique_ptr</span><span class="sy1"><</span>D, <a href="cpp-utility-functional-function.html"><span class="kw1058">std::<span class="me2">function</span></span></a><span class="sy1"><</span><span class="kw4">void</span><span class="br0">(</span>D<span class="sy2">*</span><span class="br0">)</span><span class="sy1">>></span> p<span class="br0">(</span>new D, <span class="br0">[</span><span class="br0">]</span><span class="br0">(</span>D<span class="sy2">*</span> ptr<span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"destroying from a custom deleter...<span class="es1">\n</span>"</span><span class="sy4">;</span>
|
|
delete ptr<span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// p 占有 D</span>
|
|
p<span class="sy2">-</span><span class="sy1">></span>bar<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span> <span class="co1">// 调用上述 lambda 并销毁 D</span>
|
|
|
|
<a href="cpp-io-cout.html"><span class="kw1757">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"Array form of unique_ptr demo<span class="es1">\n</span>"</span><span class="sy4">;</span>
|
|
<span class="br0">{</span>
|
|
std<span class="sy4">::</span><span class="me2">unique_ptr</span><span class="sy1"><</span>D<span class="br0">[</span><span class="br0">]</span><span class="sy1">></span> p<span class="br0">{</span>new D<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="br0">}</span> <span class="co1">// 调用 ~D 3 次</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>输出:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="text source-text">
|
|
<pre class="de1">unique ownership semantics demo
|
|
D::D
|
|
D::bar
|
|
D::bar
|
|
D::~D
|
|
Runtime polymorphism demo
|
|
D::D
|
|
D::bar
|
|
D::D
|
|
D::D
|
|
D::bar
|
|
D::bar
|
|
D::bar
|
|
D::~D
|
|
D::~D
|
|
D::~D
|
|
Custom deleter demo
|
|
x
|
|
Custom lambda-expression deleter demo
|
|
D::D
|
|
D::bar
|
|
destroying from a custom deleter...
|
|
D::~D
|
|
Array form of unique_ptr demo
|
|
D::D
|
|
D::D
|
|
D::D
|
|
D::~D
|
|
D::~D
|
|
D::~D</pre></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|