对于STL或!STL,这是个问题

毫无疑问,我会select在大多数C ++编程项目中使用STL。 最近有人问我这个问题:“有没有什么情况下你不会使用STL?”

我越想到,我意识到也许应该是我select不使用STL的情况…例如,一个非常大的,长期的项目,其代码库预计将持续数年……也许自定义的容器解决scheme,恰好符合项目需求是值得的初始开销? 你怎么看,有什么情况下你会select不STL?

embedded式系统等需要严格内存要求的项目可能不适合STL,因为很难控制和pipe理从堆中取出和返回的内容。 正如Evan所提到的,编写合适的分配器可以帮助解决这个问题,但是如果您计算每个使用或涉及内存碎片的字节,那么手动推出针对您的特定问题量身定制的解决scheme可能更为明智,因为STL已经过优化为最一般的用法。

您也可以select不使用STL来处理特定情况,因为存在更多适用的不在当前标准中的容器,例如boost :: array或boost :: unordered_map。

不使用STL的主要原因是:

  1. 你的C ++实现是旧的,并有可怕的模板支持。
  2. 您不能使用dynamic内存分配。

两者在实践中都是非常不寻常的要求。

对于一个长期的项目来说,将自己的容器与STL的function重叠在一起将会增加维护和开发成本。

使用stl有很多好处。 对于长期项目来说,收益大于成本。

  1. 新的程序员能够从第一天就了解容器,让他们有更多的时间来学习项目中的其他代码。 (假设他们已经像任何有能力的C ++程序员一样知道STL)
  2. 修复容器中的错误会浪费时间来增强业务逻辑。
  3. 很可能你不会写他们,因为STL是实现的。

这就是说,STL容器根本不处理并发。 因此,在需要并发的环境中,我会使用其他容器,如Intel TBB并发容器。 这些更高级的使用细粒度locking,使不同的线程可以同时修改容器,你不必序列化访问容器。

通常情况下,我发现最好的方法是使用STL和自定义分配器,而不是用手工卷取代STL容器。 关于STL的好处是你只为你使用的东西付费。

我认为这是一个典型的构buildvs购买场景。 不过,我认为在这种情况下,我几乎总是会“买”,并使用STL–或者更好的解决scheme(也许来自Boost),然后再滚动我自己的。 你应该把重点放在你的应用程序的大部分工作上,而不是它所使用的构件。

我真的不这么认为。 在制作我自己的容器时,我甚至会尝试使这些容器与STL兼容,因为通用algorithm的function太大而无法放弃。 STL至less应该名义上使用,即使你只是写自己的容器,并专门为它的每一个algorithm。 这样,每个sortingalgorithm都可以被调用sort(c.begin(),c.end())。 如果你专门sorting,以获得相同的效果,即使它工作不同。

Symbian编码。

STLPort支持Symbian 9,所以使用STL的情况比以前更弱(“它不可用”是一个非常令人信服的情况),但是STL对于所有的Symbian库仍然是陌生的,所以可能比只是更麻烦用Symbian的方式做事。

当然,这可能是由于这样的理由,Symbian的编码不是“一个C ++编程项目”。

我所做过的大部分项目都采用比任何真正可用的STL版本更早的代码库方式,因此我们select不介绍它。

出现这种情况的一种情况是当你已经使用一个已经提供了你需要的STL能力的外部库时。 例如,我公司在空间有限的领域开发应用程序,并已经使用Qt作为开窗工具包。 由于Qt提供类似STL的容器类,所以我们使用这些类而不是将STL添加到我们的项目中。

我发现在multithreading代码中使用STL存在问题。 即使不跨线程共享STL对象,许多实现使用非线程安全结构(如++用于引用计数而不是互锁增量样式,或者具有非线程安全的分配器)。

在这些情况下,我仍然select使用STL并解决问题(有足够的钩子来获得你想要的)。

即使你select自己的集合,对迭代器使用STL样式也是一个好主意,这样你就可以使用仅在迭代器上运行的algorithm和其他STL函数。

我已经看到的主要问题是不得不与不依赖于抛出的operator new的遗留代码进行整合。

我大约在1984年左右开始编程C,从未使用过STL。 多年来,我已经推出了自己的函数库,当STL不稳定或者缺乏跨平台支持时,它们已经发展壮大。 我的通用库已经发展到包括其他人的代码(主要是libjpeg,libpng,ffmpeg,mysql等),还有一些其他的代码,我宁愿将外部代码的数量降到最低。 我敢肯定,STL很棒,但坦率地说,我对我的工具箱中的项目很满意,现在看不到需要使用更多的工具。 但是我确实看到了新程序员可以通过使用STL而不必从头开始编写代码的巨大飞跃。

标准C ++反过来允许一些迭代器操作的实现抛出exception 。 在某些情况下,这种可能性可能会有问题。 因此,您可能会实现自己的简单容器,保证不会为关键操作抛出exception。

介绍:

STL是一个伟大的图书馆,在许多情况下是有用的,但它确实不能解决所有的情况。 回答STL或!STL就像回答“STL是否满足您的需要或不这样做?”

STL的优点

  • 在大多数情况下,STL有一个适合给定解决scheme的容器。
  • 这是有据可查的
  • 这是众所周知的(程序员通常已经知道它,进入一个项目更短)
  • 它被testing和稳定。
  • 它是跨平台的
  • 它包含在每个编译器中(不添加第三个库依赖项)
  • STL已经实施并准备就绪
  • STL很有光泽,…

STL的对比

它不需要一个简单的Graph,Red-Black Tree或者一个非常复杂的元素数据库,通过量子计算机来pipe理并发访问。 事实是,STL不会,也不会解决所有的问题。

以下几个方面只是一些例子,但基本上是这个事实的结果:STL是一个有限的真正的图书馆。

  • 例外情况:STL对exception进行中继,所以如果由于某种原因你不能接受exception(例如,安全关键),则不能使用STL。 对! exception可能会被禁用,但是这并不能解决STL中继的devise,并最终导致崩溃。

  • 需要特定的(尚未包含的)数据结构:graphics,树等

  • 复杂性的特殊约束:您可能会发现STL通用容器并不是您的瓶颈代码的最佳select。

  • 并发性考虑:要么需要并发性,STL不提供你所需要的(例如,由于双向[] operator读写器locking不能(容易地)被使用。 要么你可以devise一个容器,利用multithreading来获得更快的访问/search/插入/不pipe。

  • STL需要适合您的需求,但是反过来也是如此:您需要满足STL的需求。 不要尝试在1K的非托pipeRAM的embedded式微控制器中使用std::vector

  • 与其他库的兼容性:可能出于历史原因,你使用的库不接受STL(例如QtWidgets使用它自己的QList)。 在两个方向转换容器可能不是最好的解决scheme。


实现你自己的容器

看完之后,你可以这样想:“ 呃,我确定我可以为STL做一些比我更好的事情。 ”等等!

正确地实施你的容器变得非常迅速是一个巨大的任务:它不仅是实施一些工作,你可能必须:

  • 详细logging,包括限制,algorithm复杂度等。
  • 预计错误,并解决它们
  • 传入额外的需求:你知道,这个function缺失,types之间的这种转换等
  • 过了一段时间,你可能想重构,并改变所有的依赖(太迟了?)
  • ….

在代码中深入使用的代码像一个容器,这是需要时间来实现的,而且应该是小心翼翼的。


使用第三方库

不STL不一定意味着自定义。 networking上有很多优秀的图书馆,甚至有许可的开源许可证。

添加或不添加第三方库是另一个话题,但值得考虑。