190 lines
21 KiB
HTML
190 lines
21 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>C++ 具名要求:知分配器容器 (AllocatorAwareContainer)</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_named_req_AllocatorAwareContainer 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%">C++ 具名要求:</span><span style="font-style:italic">知分配器容器</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(AllocatorAwareContainer)</span></h1>
|
|
<div id="bodyContent">
|
|
<div id="contentSub"><span class="subpages">< <a href="cpp.html">cpp</a>‎ | <a href="cpp-named_req.html">named req</a></span></div>
|
|
<div id="mw-content-text" lang="zh" dir="ltr" class="mw-content-ltr" xml:lang="zh">
|
|
<p><strong class="selflink"><span style="font-style:italic">知分配器容器</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(AllocatorAwareContainer)</span></strong> 是<a href="cpp-named_req-Container.html"><span style="font-style:italic">容器</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(Container)</span></a> ,其保有一个<a href="cpp-named_req-Allocator.html"><span style="font-style:italic">分配器</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(Allocator)</span></a> 实例,并于其所有成员函数中用该实例来分配及解分配内存,并于这个内存中构造及销毁对象的(这种对象可以是容器元素,结点,或对于无序容器为桶数组)<span class="t-rev-inl t-since-cxx23"><span>,除了 <span class="t-lc"><a href="cpp-string-basic_string.html">std::basic_string</a></span> 特化不用分配器构造/析构其元素</span> <span><span class="t-mark-rev t-since-cxx23">(C++23 起)</span></span></span>。</p>
|
|
<p>下列规则适用于容器的构造</p>
|
|
<ul>
|
|
<li><span style="font-style:italic">知分配器容器</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(AllocatorAwareContainer)</span> 的复制构造函数,通过在正在复制的容器的分配器上调用 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-memory-allocator_traits.html"><span class="kw701">std::<span class="me2">allocator_traits</span></span></a><span class="sy1"><</span>allocator_type<span class="sy1">></span><span class="sy4">::</span><span class="me2">select_on_container_copy_construction</span></span></span> 获得自己的分配器实例。</li>
|
|
<li>移动构造函数通过从属于旧容器的分配器进行移动构造,获得其自己的分配器实例。</li>
|
|
<li>所有其他构造函数均接收一个 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> allocator_type<span class="sy3">&</span></span></span> 形参。</li>
|
|
</ul>
|
|
<p>仅有的替换分配器的方式是进行移动赋值、复制赋值及交换:</p>
|
|
<ul>
|
|
<li>仅当 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-memory-allocator_traits.html"><span class="kw701">std::<span class="me2">allocator_traits</span></span></a><span class="sy1"><</span>allocator_type<span class="sy1">></span><span class="sy4">::</span><span class="me2">propagate_on_container_copy_assignment</span><span class="sy4">::</span><span class="me2">value</span></span></span> 为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw2">true</span></span></span> 时,复制赋值才会替换分配器</li>
|
|
<li>仅当 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-memory-allocator_traits.html"><span class="kw701">std::<span class="me2">allocator_traits</span></span></a><span class="sy1"><</span>allocator_type<span class="sy1">></span><span class="sy4">::</span><span class="me2">propagate_on_container_move_assignment</span><span class="sy4">::</span><span class="me2">value</span></span></span> 为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw2">true</span></span></span> 时,移动赋值才会替换分配器</li>
|
|
<li>仅当 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-memory-allocator_traits.html"><span class="kw701">std::<span class="me2">allocator_traits</span></span></a><span class="sy1"><</span>allocator_type<span class="sy1">></span><span class="sy4">::</span><span class="me2">propagate_on_container_swap</span><span class="sy4">::</span><span class="me2">value</span></span></span> 为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw2">true</span></span></span> 时,交换才会替换分配器。特别是它将通过对非成员函数 swap 的无限定的调用来交换分配器实例,见<a href="cpp-named_req-Swappable.html"><span style="font-style:italic">可交换</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(Swappable)</span></a> 。</li>
|
|
</ul>
|
|
<p>注:若 <code>propagate_on_container_swap</code> 为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw2">false</span></span></span>,则交换两个拥有不相等分配器的容器是未定义行为。</p>
|
|
<ul>
|
|
<li>访问器 <code>get_allocator()</code> 获得构造容器时所用的,或为最近的分配器替换操作所安装的分配器的一个副本。</li>
|
|
</ul>
|
|
<h3><span class="mw-headline" id=".E8.A6.81.E6.B1.82">要求</span></h3>
|
|
<h4><span class="mw-headline" id=".E5.87.A1.E4.BE.8B">凡例</span></h4>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td><code><b>X</b></code></td>
|
|
<td>容器类型</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code><b>T</b></code></td>
|
|
<td>元素类型</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code><b>A</b></code></td>
|
|
<td><code><b>T</b></code> 的分配器</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code><b>a</b></code>, <code><b>b</b></code></td>
|
|
<td><code><b>X</b></code> 类型的对象(非 const 左值)</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code><b>t</b></code></td>
|
|
<td><code><b>X</b></code> 类型的对象(左值或 const 右值)</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code><b>rv</b></code></td>
|
|
<td><code><b>X</b></code> 类型的对象(非 const 右值)</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code><b>m</b></code></td>
|
|
<td><code><b>A</b></code> 类型的对象</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code><b>Q</b></code></td>
|
|
<td>分配器类型</td>
|
|
</tr>
|
|
</table>
|
|
<table class="wikitable">
|
|
<tr>
|
|
<th>表达式</th>
|
|
<th>返回类型</th>
|
|
<th>前提/要求</th>
|
|
<th>后置/效应</th>
|
|
<th>复杂度</th>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">allocator_type</span></span></td>
|
|
<td><code><b>A</b></code></td>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">allocator_type<span class="sy4">::</span><span class="me2">value_type</span></span></span> 必须与 <span class="t-c"><span class="mw-geshi cpp source-cpp">X<span class="sy4">::</span><span class="me2">value_type</span></span></span> 相同</td>
|
|
<td></td>
|
|
<td>编译时</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">get_allocator<span class="br0">(</span><span class="br0">)</span></span></span></td>
|
|
<td><code><b>A</b></code></td>
|
|
<td></td>
|
|
<td></td>
|
|
<td>常数</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">X u<span class="sy4">;</span></span></span></td>
|
|
<td></td>
|
|
<td><code><b>A</b></code> <a href="cpp-named_req-DefaultConstructible.html"><span style="font-style:italic">可默认构造</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(DefaultConstructible)</span></a></td>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">u.<span class="me1">empty</span><span class="br0">(</span><span class="br0">)</span> <span class="sy1">==</span> <span class="kw2">true</span> <span class="sy3">&&</span> u.<span class="me1">get_allocator</span><span class="br0">(</span><span class="br0">)</span> <span class="sy1">==</span> A<span class="br0">(</span><span class="br0">)</span></span></span></td>
|
|
<td>常数</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">X u<span class="br0">(</span>m<span class="br0">)</span><span class="sy4">;</span></span></span></td>
|
|
<td></td>
|
|
<td></td>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">u.<span class="me1">empty</span><span class="br0">(</span><span class="br0">)</span> <span class="sy1">==</span> <span class="kw2">true</span> <span class="sy3">&&</span> u.<span class="me1">get_allocator</span><span class="br0">(</span><span class="br0">)</span> <span class="sy1">==</span> m</span></span></td>
|
|
<td>常数</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">X u<span class="br0">(</span>t,m<span class="br0">)</span><span class="sy4">;</span></span></span></td>
|
|
<td></td>
|
|
<td><code><b>T</b></code> <a href="cpp-named_req-CopyInsertable.html"><span style="font-style:italic">可复制插入</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(CopyInsertable)</span></a> 到 <code><b>X</b></code></td>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">u <span class="sy1">==</span> t <span class="sy3">&&</span> u.<span class="me1">get_allocator</span><span class="br0">(</span><span class="br0">)</span> <span class="sy1">==</span> m</span></span></td>
|
|
<td>线性</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">X u<span class="br0">(</span>rv<span class="br0">)</span><span class="sy4">;</span></span></span></td>
|
|
<td></td>
|
|
<td><code><b>A</b></code> 的移动构造函数必须不抛异常</td>
|
|
<td><code><b>u</b></code> 拥有与 <code><b>rv</b></code> 构造前相同的元素和相等的分配器</td>
|
|
<td>常数</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">X u<span class="br0">(</span>rv,m<span class="br0">)</span><span class="sy4">;</span></span></span></td>
|
|
<td></td>
|
|
<td><code><b>T</b></code> <a href="cpp-named_req-MoveInsertable.html"><span style="font-style:italic">可移动插入</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(MoveInsertable)</span></a> 到 <code><b>X</b></code></td>
|
|
<td><code><b>u</b></code> 的元素与 <code><b>rv</b></code> 的相同或是其副本,且 <span class="t-c"><span class="mw-geshi cpp source-cpp">u.<span class="me1">get_allocator</span><span class="br0">(</span><span class="br0">)</span> <span class="sy1">==</span> m</span></span></td>
|
|
<td>若 <span class="t-c"><span class="mw-geshi cpp source-cpp">m <span class="sy1">==</span> rv.<span class="me1">get_allocator</span><span class="br0">(</span><span class="br0">)</span></span></span> 则为常数,否则为线性</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">a <span class="sy1">=</span> t</span></span></td>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">X<span class="sy3">&</span></span></span></td>
|
|
<td><code><b>T</b></code> <a href="cpp-named_req-CopyInsertable.html"><span style="font-style:italic">可复制插入</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(CopyInsertable)</span></a> 到 <code><b>X</b></code> 且<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></td>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">a <span class="sy1">==</span> t</span></span></td>
|
|
<td>线性</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">a <span class="sy1">=</span> rv</span></span></td>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">X<span class="sy3">&</span></span></span></td>
|
|
<td>若分配器将<i>不</i>被移动赋值所替换(见上文),则 <code><b>T</b></code> <a href="cpp-named_req-MoveInsertable.html"><span style="font-style:italic">可移动插入</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(MoveInsertable)</span></a> 到 <code><b>X</b></code> 并<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></td>
|
|
<td><code><b>a</b></code> 的所有既存元素被移动赋值或销毁;若 <code><b>a</b></code> 与 <code><b>rv</b></code> 不指代同一对象则 <code><b>a</b></code> 等于 <code><b>rv</b></code> 赋值前所拥有的值</td>
|
|
<td>线性</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">a.<span class="me1">swap</span><span class="br0">(</span>b<span class="br0">)</span></span></span></td>
|
|
<td>void</td>
|
|
<td></td>
|
|
<td>交换 <code><b>a</b></code> 与 <code><b>b</b></code> 的内容</td>
|
|
<td>常数</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E6.B3.A8.E8.A7.A3">注解</span></h3>
|
|
<p>具分配器容器始终调用 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-memory-allocator_traits.html"><span class="kw701">std::<span class="me2">allocator_traits</span></span></a><span class="sy1"><</span>A<span class="sy1">></span><span class="sy4">::</span><span class="me2">construct</span><span class="br0">(</span>m, p, args<span class="br0">)</span></span></span> 在 <code>p</code> 中用 <code>args</code> 来构造一个 <code>A</code> 类型的对象,其中 <span class="t-c"><span class="mw-geshi cpp source-cpp">m <span class="sy1">==</span> get_allocator<span class="br0">(</span><span class="br0">)</span></span></span>。<span class="t-rev-inl t-until-cxx20"><span><span class="t-lc"><a href="cpp-memory-allocator.html">std::allocator</a></span> 中默认的 <code>construct</code> 调用 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy4">::</span><span class="me2">new</span><span class="br0">(</span><span class="br0">(</span><span class="kw4">void</span><span class="sy2">*</span><span class="br0">)</span>p<span class="br0">)</span> T<span class="br0">(</span>args<span class="br0">)</span></span></span></span> <span><span class="t-mark-rev t-until-cxx20">(C++20 前)</span></span></span><span class="t-rev-inl t-since-cxx20"><span><span class="t-lc"><a href="cpp-memory-allocator.html">std::allocator</a></span> 无 <code>construct</code> 成员,而在构造元素时 <span class="t-c"><span class="mw-geshi cpp source-cpp">std<span class="sy4">::</span><span class="me2">construct_at</span><span class="br0">(</span>p, args<span class="br0">)</span></span></span> 得到调用</span> <span><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></span></span>,但特化的分配器可以选择不同的定义。</p>
|
|
<h3><span class="mw-headline" id=".E6.A0.87.E5.87.86.E5.BA.93">标准库</span></h3>
|
|
<p>所有标准库容器,除了 <span class="t-lc"><a href="cpp-container-array.html">std::array</a></span>,都是<span style="font-style:italic">知分配器容器</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(AllocatorAwareContainer)</span> :</p>
|
|
<ul>
|
|
<li><span class="t-lc"><a href="cpp-string-basic_string.html">std::basic_string</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-deque.html">std::deque</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-forward_list.html">std::forward_list</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-list.html">std::list</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-vector.html">std::vector</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-map.html">std::map</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-multimap.html">std::multimap</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-set.html">std::set</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-multiset.html">std::multiset</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-unordered_map.html">std::unordered_map</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-unordered_multimap.html">std::unordered_multimap</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-unordered_set.html">std::unordered_set</a></span></li>
|
|
<li><span class="t-lc"><a href="cpp-container-unordered_multiset.html">std::unordered_multiset</a></span></li>
|
|
</ul>
|
|
<h3><span class="mw-headline" id=".E7.BC.BA.E9.99.B7.E6.8A.A5.E5.91.8A">缺陷报告</span></h3>
|
|
<p>下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。</p>
|
|
<table class="dsctable" style="font-size:0.8em">
|
|
<tr>
|
|
<th>DR</th>
|
|
<th>应用于</th>
|
|
<th>出版时的行为</th>
|
|
<th>正确行为</th>
|
|
</tr>
|
|
<tr>
|
|
<td><a rel="nofollow" class="external text" href="https://cplusplus.github.io/LWG/issue2839">LWG 2839</a></td>
|
|
<td>C++11</td>
|
|
<td>不允许标准容器的自移动赋值</td>
|
|
<td>容许但结果未指定</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|