跳到主要内容

节点句柄 (C++17)

自 C++17 起
template</* unspecified */>
class /* node-handle */;

关联容器 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 调用可以生成空节点句柄。

当元素由节点句柄拥有时获取的指向元素的指针和引用,如果该元素成功插入到容器中,则会失效。

对于所有映射容器(std::mapstd::multimapstd::unordered_mapstd::unordered_multimap),如果存在 std::pairstd::pair 的用户定义特化,则涉及节点句柄的操作行为是未定义的。

成员类型

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

成员函数


构造函数

// 1)
constexpr /* node-handle */() noexcept;
// 2)
/* node-handle */ (/* node-handle */&& nh) noexcept;
  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_assignment 为 true,则从 nh 移动赋值分配器;
  • nh 设置为空状态。

如果节点不为空且 std::allocator_traits<allocator_type>::propagate_on_container_move_assignment 为 false 且分配器不相等,则行为未定义。

参数

nh - 具有相同类型(不一定是相同容器)的节点句柄

返回

*this

异常

不抛出任何异常。

注意

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


析构函数

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

empty

直到 C++20
bool empty() const noexcept;
自 C++20 起
[[nodiscard]] bool empty() const noexcept;

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


operator bool

explicit operator bool() const noexcept;

如果节点句柄为空,则转换为 false,否则转换为 true


get_allocator

allocator_type get_allocator() const;

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

异常

不抛出任何异常。


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

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

异常

不抛出任何异常。


仅限映射容器
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(/* see below */);
  • 交换容器节点的所有权;
  • 如果一个节点为空或者两个节点都不为空且 std::allocator_traits<allocator_type>::propagate_on_container_swap 为 true,则也交换分配器。

如果两个节点都不为空且 std::allocator_traits<allocator_type>::propagate_on_container_swap 为 false 且分配器不相等,则行为未定义。

异常

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 是参数的关联类时)找到。


节点句柄 (C++17)

自 C++17 起
template</* unspecified */>
class /* node-handle */;

关联容器 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 调用可以生成空节点句柄。

当元素由节点句柄拥有时获取的指向元素的指针和引用,如果该元素成功插入到容器中,则会失效。

对于所有映射容器(std::mapstd::multimapstd::unordered_mapstd::unordered_multimap),如果存在 std::pairstd::pair 的用户定义特化,则涉及节点句柄的操作行为是未定义的。

成员类型

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

成员函数


构造函数

// 1)
constexpr /* node-handle */() noexcept;
// 2)
/* node-handle */ (/* node-handle */&& nh) noexcept;
  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_assignment 为 true,则从 nh 移动赋值分配器;
  • nh 设置为空状态。

如果节点不为空且 std::allocator_traits<allocator_type>::propagate_on_container_move_assignment 为 false 且分配器不相等,则行为未定义。

参数

nh - 具有相同类型(不一定是相同容器)的节点句柄

返回

*this

异常

不抛出任何异常。

注意

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


析构函数

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

empty

直到 C++20
bool empty() const noexcept;
自 C++20 起
[[nodiscard]] bool empty() const noexcept;

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


operator bool

explicit operator bool() const noexcept;

如果节点句柄为空,则转换为 false,否则转换为 true


get_allocator

allocator_type get_allocator() const;

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

异常

不抛出任何异常。


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

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

异常

不抛出任何异常。


仅限映射容器
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(/* see below */);
  • 交换容器节点的所有权;
  • 如果一个节点为空或者两个节点都不为空且 std::allocator_traits<allocator_type>::propagate_on_container_swap 为 true,则也交换分配器。

如果两个节点都不为空且 std::allocator_traits<allocator_type>::propagate_on_container_swap 为 false 且分配器不相等,则行为未定义。

异常

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 是参数的关联类时)找到。