节点句柄 (C++17)

来自cppreference.com
< cpp‎ | container


template</* 未指定 */>
class /* node-handle */;
(C++17 起)

关联容器 std::setstd::mapstd::multisetstd::multimapstd::unordered_setstd::unordered_mapstd::unordered_multisetstd::unordered_multimap 是基于节点的数据结构,并且可以将这些容器的节点作为具有称作 节点句柄 的未指定类型的对象提取出来。

节点句柄是仅移动类型,它拥有并提供对节点中存储的元素(value_type)的访问,也提供对元素键部分(key_type)和被映射部分(mapped_type)的非 const 访问。如果节点句柄在持有节点时析构,那么就会用容器的分配器正确地析构节点。节点句柄含有容器分配器的副本,这是节点句柄能在容器生存期外存在所必需的。

节点句柄的确切类型(此处显示为 /* node-handle */)是未指定的,但每个容器通过它的成员 node_type 暴露它的节点句柄类型。

节点句柄能用于在两个有相同键、值和分配器类型(忽略比较或散列/相等性)的关联容器间传递节点的所有权,而无需调用任何容器元素上的复制/移动操作(这种操作被称为“接合”)。在唯一和非唯一容器间传递也是容许的:来自 std::map 的节点句柄可被插入 std::multimap,但不能插入 std::unordered_mapstd::set

节点句柄可以为空,这种情况下它不保有元素和分配器。默认构造和被移动后的节点句柄是空的。另外,空的节点句柄可由对容器成员函数 extract 的失败调用产生。

如果成功将元素插入容器,那么在该元素被节点句柄占有期间获得的到该元素的引用或指针会失效。

对于所有 key_typeKmapped_typeT 的映射容器(std::mapstd::multimapstd::unordered_mapstd::unordered_multimap),如果对 std::pair<K, T>std::pair<const K, T> 存在 std::pair 的用户定义特化,那么涉及节点句柄的操作行为未定义。

成员类型

成员类型 定义
key_type(仅限 map 容器) 在节点存储的关键
mapped_type(仅限 map 容器) 在节点存储的元素的被映射部分
value_type(仅限集合容器) 节点中存储的元素
allocator_type 销毁元素时使用的分配器

成员函数

构造函数

constexpr /* node-handle */() noexcept;
(1)
/* node-handle */ (/* node-handle */&& nh) noexcept;
(2)
1) 默认构造函数初始化节点句柄为空状态。
2) 移动构造函数从 nh 取走容器元素所有权,移动构造成员分配器,并令 nh 留在空状态。

参数

nh - 同类型的节点句柄(不必属于相同容器)

注解

节点句柄是仅移动的,不定义复制构造函数。

operator=

/* node-handle */& operator=(/* node-handle */&& nh);
  • 如果节点句柄非空,
  • 那么通过调用 std::allocator_traits<allocator_type>::destroy 销毁此节点句柄管理的容器元素对象中的 value_type 子对象;
  • 通过调用 std::allocator_traits<allocator_type>::rebind_traits</* container-node-type */>::deallocate 解分配容器元素;
  • nh 获得容器元素的所有权;
  • 如果节点句柄为空(从而不含分配器)或 std::allocator_traits<allocator_type>::propagate_on_container_move_assignmenttrue,那么从 nh 移动赋值分配器;
  • 设置 nh 为空状态。

如果节点非空且 std::allocator_traits<allocator_type>::propagate_on_container_move_assignmentfalse 且分配器比较不相等,那么行为未定义。

参数

nh - 同类型的节点句柄(不必属于相同容器)

返回

*this

异常

不抛出。

注解

节点句柄是仅移动的,不定义复制赋值。

析构函数

~/* node-handle */();
  • 如果节点句柄非空,
  • 那么通过调用 std::allocator_traits<allocator_type>::destroy,销毁此节点句柄管理的容器元素对象中的 value_type 子对象;
  • 通过调用 std::allocator_traits<allocator_type>::rebind_traits</* container-node-type */>::deallocate 解分配容器元素。

empty

bool empty() const noexcept;

节点句柄为空时返回 true,否则返回 false

operator bool

explicit operator bool() const noexcept;

节点句柄为空时转换成 false,否则转换成 true

get_allocator

allocator_type get_allocator() const;

返回存储的分配器(它是源容器的分配器副本)的副本。节点句柄为空时行为未定义。

异常

不抛出。

value

value_type& value() const;
(仅限集合容器)

返回到此节点句柄管理的容器元素对象中的 value_type 子对象的引用。节点句柄为空时行为未定义。

异常

不抛出。

key

key_type& key() const;
(仅限映射容器)

返回到此节句柄柄管理的容器元素对象中的 value_type 子对象的 key_type 成员的非 const 引用。节点句柄为空时行为未定义。

异常

不抛出。

注解

此函数使得能够修改从映射提取的节点的键,再重新插入到映射,而无需复制或移动元素。

mapped

mapped_type& mapped() const;
(仅限映射容器)

返回到此节点句柄管理的容器元素对象中的 value_type 子对象的 mapped_type 成员的引用。节点句柄为空时行为未定义。

异常

不抛出。

swap

void swap(/* node-handle */& nh) noexcept(/* 见下文 */);
  • 交换容器节点的所有权;
  • 如果一个节点为空或两个节点均为非空且 std::allocator_traits<allocator_type>::propagate_on_container_swaptrue,那么一同交换分配器。

如果两个节点均为非空且 allocator_traits<allocator_type>::propagate_on_container_swapfalse 而分配器比较不相等,那么行为未定义。

异常

noexcept 说明:  
noexcept(std::allocator_traits<allocator_type>::propagate_on_container_swap::value ||
         std::allocator_traits<allocator_type>::is_always_equal::value)

非成员函数

swap

friend void swap(/* node-handle */& x, /* node-handle */& y) noexcept(noexcept(x.swap(y)));

实际上执行 x.swap(y)

此函数对常规的无限定有限定查找不可见,而只能在 node-handle 为实参的关联类时由实参依赖查找找到。