STL有什么好处?

Zyg*_*rob 30 c++ stl

我是一名尝试学习C++的Java开发人员.我有很多次在互联网上阅读(包括Stack Overflow),STL是你可以用任何语言获得的最佳馆藏库.(对不起,我没有任何引用)

然而,在研究了一些STL之后,我真的没有看到是什么让STL如此特别.您能否详细说明STL与其他语言的集合库之间的区别,并使其成为最佳的集合库?

Dea*_*ing 26

它不是那么"伟大"或"你能用*任何*语言获得的最佳馆藏图书馆",但它确实与许多其他语言有着不同的理念.

特别是,标准C++库使用通用编程范例,而不是像Java和C#这样的语言中常见的面向对象范例.也就是说,你有一个什么"通用"的定义iterator应该是,然后你就可以实现该功能for_each或者sort或者max_element是采用任何一个实现类的iterator模式,而无需实际从一些基本的"迭代器"界面或任何继承.

  • 实际上,"静态鸭子打字"方法也由C#编译器应用于容器.`foreach`可以枚举任何具有`GetEnumerator`方法的对象,并且集合初始化程序可以处理任何`IEnumerable`对象**也*具有`Add`方法 - 所以它只是查找方法名称和签名,无论类型如何它们是在C++模板中定义的. (2认同)
  • 哈!我看到一个"交互者" - 我希望每次输入时都有1美元.对我们工作的肌肉记忆:( (2认同)
  • @spong:该死的,什么时候让Intellisense自动修复我的错误:) (2认同)
  • @Daniel Earwicker:'int'和'char*'没有在C#中实现GetEnumerator,但STL可以处理这些.Duck Typing是关于类型的行为,而不是先决条件. (2认同)

Mat*_* M. 23

STL有什么好处?

STL很棒,因为它很早就构思出来,但却成功地使用了C++通用编程范例.

它有效地分离了数据结构:vector,map,...和算法来对它们进行操作copy,transform......采取的模板,利用这样做.

它巧妙地解耦了问题并为通用容器提供了定制钩子(ComparatorAllocator模板参数).

由于编译器优化,结果非常优雅(DRY原则)并且非常高效,因此给定容器的手动生成算法不太可能做得更好.

它还意味着它易于扩展:您可以使用您希望的接口创建自己的容器,只要它暴露符合STL的迭代器,您就可以使用STL算法!

由于使用了traits,你甚至可以通过普通指针在C-array上应用算法!说说向后兼容!

但是,它可能(也许)更好......

STL的优点是什么?

我真的很生气,总是必须使用迭代器,我真的代表能够写:std::foreach(myVector, [](int x) { return x+1;});因为面对它,大多数时候你想迭代整个容器......

但更糟糕的是因为:

set<int> mySet = /**/;

set<int>::const_iterator it = std::find(mySet.begin(), mySet.end(), 1005); // [1]
set<int>::const_iterator it = mySet.find(1005); // [2]
Run Code Online (Sandbox Code Playgroud)

[1]并且[2]执行完全不同,导致[1]O(n)复杂度,同时[2]具有O(log n)复杂度!这里的问题是迭代器抽象得太多了.

我并不是说迭代器不值得,我只是意味着提供一个专门用于迭代器的接口是一个糟糕的选择.

我更喜欢自己的容器视图的想法,例如检查Boost.MPL做了什么.通过视图,您可以使用(惰性)转换层操纵容器.它使得非常有效的结构允许您过滤掉一些元素,转换其他元素等...

结合的观点概念检查的想法会,我认为,生产用于STL算法更好的界面(和解决这个问题find,lower_bound,upper_bound,equal_range问题).

它还可以避免使用错误定义的迭代器范围和由此产生的未定义行为的常见错误......

  • 至少在C++ 0x中,你将为迭代器提供for-each循环访问! (2认同)
  • 在C++中可以使用视图和概念检查(尽管您可能需要努力获取它们).视图类似于容器适配器(具有委托存储)和Boost.Concept是活着和踢.我遇到的问题是迭代器,而不是C++ :) (2认同)

wil*_*ell 21

我喜欢STL的是它有多强大.它很容易扩展.有些人抱怨它很小,缺少许多常见的算法或迭代器.但正是当你看到添加你需要的缺失组件是多么容易的时候.不仅如此,小而美:你有大约60种算法,少量容器和少量迭代器; 但功能是这些产品的顺序.容器的接口仍然小而简单.

因为编写小巧,简单的模块化算法是时尚,所以更容易发现组件中的错误和漏洞.然而,与算法和迭代器一样简单,它们非常强大:您的算法将与许多现有的和尚未编写的迭代器一起使用,并且您的迭代器可以与许多现有的迭代器一起使用,而且还可以使用编写算法.

我也很喜欢STL的简单性.你有容器,你有迭代器,你有算法.就是这样(我躺在这里,但这是舒适的图书馆所需要的).您可以将不同的算法与不同的迭代器混合使用不同的容器.确实,其中一些有限制禁止他们与他人合作,但总的来说有很多可以玩的.

Niklaus Wirth说程序是算法加数据结构.这正是STL的意义所在.如果Ruby和Python是字符串超级英雄,那么C++和STL是算法和容器的超级英雄.

  • 实际上,我认为你会发现它是Wirth,而不是Knuth--这是他(wirth)书籍的标题. (3认同)

Bil*_*eal 13

STL的容器很不错,但它们与其他编程语言中的容器差别不大.使STL容器有用的原因是它们与算法完美地结合在一起.标准算法提供的灵活性在其他编程语言中是无与伦比的.

没有算法,容器就是这样.容器.没什么特别的.

现在,如果您只讨论C++的容器库,那么您不太可能找到STL提供的库和测试库,如果没有别的,因为它们是标准的.

  • 更不用说在任何体面的编译器上,STL都是超级优化的. (3认同)

fre*_*low 13

STL与内置类型相得益彰.A std::array<int, 5>就是这样 - 一个5 ints 的数组,在32位平台上消耗20个字节.

java.util.Arrays.asList(1, 2, 3, 4, 5)另一方面,返回对包含对数组引用的对象的引用,该数组包含对包含ints的Integer对象的引用.是的,这是3级间接,我不敢预测消耗的字节数;)

  • "我不敢预测消耗多少字节" - 你无法预测它消耗了多少字节,因为例如你不知道JVM是否会在装箱时使用小整数优化.最后一级间接可能会创建5个"整数"对象,或者可能使用总是存在的5个静态整数对象. (2认同)
  • @Steve"你无法预测它消耗了多少字节" - >我想这就是为什么我不敢;-) (2认同)

Mat*_*ner 8

这不是一个直接的答案,但是当你来自Java时,我想指出这一点.与Java等价物相比,STL 非常快.

我找到了这个页面,显示了一些性能比较.一般来说,Java人员在性能对话方面非常敏感,并且声称各种各样的进步一直在发生.然而,在C/C++编译器中也出现了类似的进步.

  • 这是一个很好的观点 - 你能链接到这个数据吗? (2认同)

JBR*_*son 7

请记住,STL现在实际上已经很老了,所以其他更新的库可能具有特定的优势.鉴于年龄,它的受欢迎程度证明了原始设计的优秀程度.

我之所以说STL(仍)很棒,有四个主要原因:

Speed STL使用C++模板,这意味着编译器会生成专门为您使用库而定制的代码.例如,map将自动生成一个新类,以实现'key'类型到'value'类型的map集合.没有运行时开销,库试图找出如何有效地存储'key'和'value' - 这是在编译时完成的.由于优雅的设计,某些类型的某些操作将编译为单个汇编指令(例如,增加基于整数的迭代器).

效率 集合类具有"分配器"的概念,您可以自己提供,也可以使用库提供的仅分配足够的存储来存储数据的库.没有填充物也没有浪费.在可以更有效地存储内置类型的情况下,存在可以最佳地处理这些情况的特殊化,例如,bool的向量被处理为位域.

灵活性 您可以在任何适合的类型中使用STL中提供的容器(集合类),算法和函数.如果可以比较您的类型,可以将其放入容器中.如果它进入容器,可以对其进行排序,搜索和比较.如果你提供像'bool Predicate(MyType)'这样的函数,它可以被过滤,等等.

优雅 其他库/框架必须在每种类型的集合上实现Sort()/ Find()/ Reverse()方法.STL将这些作为单独的算法实现,它们使用您正在使用任何集合的迭代器并在该集合上盲目操作.算法并不关心你是使用Vector,List,Deque,Stack,Bag,Map - 它们只是起作用.

  • @kts:大多数C++开发人员都不太关心编译速度; 而; 我们关心运行时速度.此外,如果你使用一个糟糕的编译器,模板只会很慢 - 任何合理的最新编译器都没有问题.在构建时它会比C慢吗?大概.这并不意味着应删除该功能. (5认同)
  • @kts:虚拟指针查找不需要很长时间,不会,但它们会阻止内联.因此,不是vtable查找速度慢,它们只是阻止了可能使代码*非常快*的优化(与硬编码,手动代码相同的性能) (4认同)
  • 速度:模板会降低编译速度,虚拟指针查找不会长_that_.这不是1970年.效率:首先,矢量<bool>是一种需要死亡的憎恶.分配器不是关于效率,而是关于如何创建和删除新的"T".可扩展性:这不是STL独有的.地狱,我在java中编写了算法,它采用了`Iterator <T`>和/或`Predicate <?超级T>`. (2认同)
  • 优雅:再次,这不是STL独有的.任何通用编程语言都以相同的方式完成.OO语言(如java)提供了一种List类型,用于指定存在的排序函数.它并没有说该函数不能调用泛型排序算法.事实上,java List没有`sort`成员函数,它们按`Collections.sort`排序,这是一种静态方法. (2认同)
  • 实际上,`std :: vector <booL>`可能是一个更好的候选人提出一个问题"什么__not__这么好的STL?" (2认同)