阅读了node-handle接口的文档并研究了标准库的一些实现,我注意到node-handle类型的许多特性可以简单地通过std::unique_ptr
智能指针的特殊化来模拟。实际上,节点句柄类型的功能与std::unique_ptr
智能指针的功能非常相似。它只有一个更符合关联容器特性的接口,例如key_type和mapped_type别名以及获取底层值或key/mapped值的引用的函数。
那么,标准引入节点句柄类型比将std::unique_ptr
简单特殊化为node_type
有什么其他优点吗?
1条答案
按热度按时间j0pj023g1#
从纯哲学的Angular 来看,仅仅因为一个类型与另一个类型具有相似的接口,并不意味着该类型是多余的,应该被更通用的类型所取代。
在这个特定的例子中,这些类型并不等价。
node_handle
的主要目标之一是您不需要知道容器所使用的节点的实际类型。甚至不作为不透明类型别名;node_type
是node_handle
的特殊化,而不是内部节点类型名。另外,考虑
unique_ptr
,就其本质而言, Package 了指向某个对象的指针。有一个指针在某个时候没有被拥有,那么unique_ptr
拥有它。因此,release
是一个合理的函数:它不销毁该指针而放弃该指针。对于
node_handle
来说,这不是一个合理的函数。你没有创造那个节点,所以你没有能力摧毁它。该节点由故意对用户不透明的系统所拥有。它持有的任何指针都指向实现定义的数据结构,并且可能有多个实现定义的数据结构。但这忽略了
node_handle
的关键特性,这也是它存在的原因。node_handle
的要点是,您可以从这样的容器中提取元素,* 修改其键 *(从而影响它在容器中的位置),然后重新插入它而无需分配内存。要使用unique_ptr<T>
做到这一点,需要T
是用户可以理解并可以与之交谈的某种类型(因此可以用来修改密钥)。什么是T
?容器不能是
value_type
,因为这使得密钥类型为const
,因此不可修改。所以它必须是一个新的类型,给你一个接口来修改键的值。既然它必须是某种新的类型...你还不如直接把node_handle
做成那种类型,保存下一大堆痛苦。此外,还需要考虑分配器行为。首先,
node_handle
还存储容器的分配器的副本。这是unique_ptr
做不到的。其次,当你从一个容器移动到另一个容器时,有状态分配器可能有特殊的行为。具体地说,您可能需要在执行此操作时移动分配器。但对于许多分配者来说,你可能不会。因此,
node_handle
需要复制此行为。unique_ptr
也不能这样做。现在,您可以通过使用隐藏的(特定于容器的)类型名作为模板参数,创建一个
unique_ptr
的特殊化,并使用一个符合上述要求的不同接口来实现所有这些。但是...何必呢这是一个不同的界面,有着不同的、专门的用途。因此,请给予它自己的类型名。C++并没有用完名字。