Boost C++ 库

...世界上最受尊敬和专家设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

Boost 指针容器库

作者 Thorsten Ottosen
联系方式 [email protected][email protected]
组织奥尔堡大学计算机科学系,和 Dezide Aps
日期 2007年10月27日
版权 Thorsten Ottosen 2004-2007。使用、修改和分发受 Boost 软件许可证版本 1.0 的约束(参见 LICENSE_1_0.txt)。

概述

Boost.Pointer Container 提供了以异常安全的方式和最小的开销容纳堆分配对象的容器。该库的目标是通过建立一套用于处理面向对象特定问题的标准类、方法和设计,使 C++ 中的面向对象编程更容易。

动机

每当程序员想要一个指向堆分配对象的指针容器时,通常只有一种异常安全的方法:创建一个智能指针容器,如 boost::shared_ptr。如果出现以下情况,这种方法就不是最佳的:

  1. 存储的对象不是共享的,而是独占拥有的,或者
  1. 智能指针隐含的开销是不合适的

因此,该库提供了类似标准的容器,用于存储堆分配或克隆的对象(或者对于映射,映射的对象必须是堆分配或克隆的对象)。对于每个标准容器,都有一个指针容器等价物,它以异常安全的方式获取对象的所有权。在这方面,该库旨在解决所谓的多态类问题

指针容器的优点是

  1. 异常安全的指针存储和操作。
  1. 与使用指针容器相比,符号更方便。
  1. 可用于既不可赋值也不可复制构造的类型。
  1. 没有智能指针容器可能具有的内存开销(参见 [11][12])。
  1. 通常比使用智能指针容器更快(参见 [11][12])。
  1. 接口略微更改为指针域,而不是依赖于正常的基于值的接口。例如,现在可以pop_back()返回删除的元素。
  1. 传播常量性,这样就不能通过const_iterator.
  1. 修改对象。通过可克隆概念内置支持深拷贝语义

缺点是

  1. 不如 boost::shared_ptr 等智能指针容器灵活

当你确实需要共享语义时,这个库不是你需要的。

从 Boost v. 升级1.33.*

如果您从 Boost 的这些版本之一升级,那么有一个主要的接口更改:映射迭代器现在模仿std::map的迭代器。以前您可能编写了

for( boost::ptr_map<std::string,T>::iterator i = m.begin(), e = m.end();
     i != e; ++i )
{
  std::cout << "key:" << i.key();
  std::cout << "value:" << *i;
  i->foo(); // call T::foo()
}

现在需要将其转换为

for( boost::ptr_map<std::string,T>::iterator i = m.begin(), e = m.end();
     i != e; ++i )
{
  std::cout << "key:" << i->first;
  std::cout << "value:" << *i->second;
  i->second->foo(); // call T::foo()
}

除了上述更改之外,该库现在还引入了

中进行派生到基类的转换。另请注意,Boost.Assign 引入了对指针容器的更好支持。

从 Boost v. 升级1.34.*

由于 Sebastian Ramacher 的贡献,序列化现在是可选的。您只需包含<boost/ptr_container/serialize.hpp>或者可能只是更专业的头文件之一。

所有容器现在都是可复制构造和可赋值的。所以你现在可以做例如

boost::ptr_vector<Derived> derived = ...;
boost::ptr_vector<Base>    base( derived );
base = derived;

如示例所示,也允许派生到基类的转换。

添加了一些通用函数

VoidPtrContainer&       base();
const VoidPtrContainer& base() const;

这些函数允许直接访问包装的容器,这在您想要提供额外功能时有时是必需的。

序列中添加了一些新函数

void resize( size_type size );
void resize( size_type size, T* to_clone );

ptr_vector<T>有一些新的辅助函数可以更好地与 C 数组集成

void transfer( iterator before, T** from, size_type size, bool delete_from = true );
T**  c_array();

最后,您现在还可以通过调用“复制”和“赋值”auto_typeptrmove():

boost::ptr_vector<T>::auto_type move_ptr = ...;
return boost::ptr_container::move( move_ptr );

从 Boost v. 升级1.35.*

该库相当稳定,但支持了一些新的容器

目前还没有这些类的文档,但它们几乎与boost::ptr_set<T>, boost::ptr_map<Key,T>boost::ptr_array<T,N>分别相同。底层容器来自两个 boost 库

此外,还添加了插入迭代器

从 Boost v. 升级1.66.*

从 Boost v. 开始1.67.0,Boost.Pointer Container 将使用 Boost.Config 有条件地提供std::unique_ptr接口以及或者代替使用std::auto_ptr的接口。详细信息位于兼容智能指针页面,该页面还解释了本文档中使用

compatible-smart-ptr<T>

指示此类条件接口的约定。

对于 C++98/03 用户,此更改没有可观察到的效果。

对于 C++11/14 用户,对使用先前版本 Boost.Pointer Container 的现有代码没有影响,但现在所有采用std::auto_ptr参数的函数重载都伴随着一个采用std::unique_ptr的重载。在返回类型的情况下,仍然始终使用std::auto_ptr。但是请注意,在 C++17 之前,可以从std::unique_ptr<T>隐式构造std::auto_ptr<T>。因此,用户可以通过将任何显式提及的std::auto_ptr替换为std::unique_ptr来实现代码的现代化。此更改略微不足以进行搜索和替换转换,因为某些代码可能依赖于std::auto_ptr的可复制性。但这种情况会导致编译时错误,应该很容易修复。

尽管std::auto_ptr在 ISO C++17 中正式删除,但某些编译器或标准库供应商选择将其保留以实现向后兼容性。对于并非如此的编译器和标准库,使用 Boost v. 无法使用 C++17 编译使用 Boost.Pointer Container 的代码。1.66.*或更早版本。此情况已在 Boost v. 中修复。1.67.0.

未来发展

有迹象表明,void*实现与T*实现相比,性能略有下降。此外,T*实现更容易与算法一起安全地使用类型。因此,我预计将迁移到T*实现。

此外,克隆分配器可能被允许具有状态。这个设计需要一些思考,所以如果您对此有好的想法和用例,请随时与我联系。

此外,对 Boost.Interprocess 的支持也在待办事项列表中。

有一些请求boost::ptr_multi_index_container<T,...>。我调查了它的难度,结果证明它很困难,尽管并非不可能。但我没有资源在未来几年内实现这个庞然大物,所以如果有人真的需要这个容器,我建议他们私下与我讨论如何实现它。

致谢

以下人士提供了非常有益的帮助

参考文献

[1]Matt Austern:《"标准库:指针容器"》,C/C++ 用户杂志专家论坛。
[2]Bjarne Stroustrup,《C++ 程序设计语言》,附录 E:“标准库异常安全”
[3]Herb Sutter,《Exceptional C++》。
[4]Herb Sutter,《More Exceptional C++》。
[5]Kevlin Henney:《"从机制到方法:猫的安全堆叠"》,C++ 专家论坛,2002 年 2 月。
[6]我见过的一些早期指针容器尝试是相当有趣的 NTLpointainer。在撰写本文时,这两个库都不是异常安全的,并且可能会泄漏。
[7]国际标准,程序设计语言 --- C++,ISO/IEC 14882,1998。尤其参见第 23 节。
[8]C++ 标准库已解决问题列表(修订版 27),问题 218,算法没有使用二元谓词对象进行默认比较
[9]C++ 标准库活跃问题列表(修订版 27),问题 226,用户提供的命名空间 std 函数模板的特化或重载
[10]Harald Nowak,“一种用于向量的 remove_if”,C/C++ 用户杂志,2001 年 7 月。
[11](1, 2) Boost 智能指针 计时
[12](1, 2) NTL:数组 vs std::vector 和 boost::shared_ptr
[13]Kevlin Henney,《空对象》,2002 年。

版权Thorsten Ottosen 2004-2006。