为何某些公司不允许使用C++ STL?

说几个STL的缺点吧,虽然都是在比较极端的情况下出现,但是对于一些大项目还是会遇到的

1. 代码膨胀问题
每一个实例化过的模板类,都会膨胀出一份独立的代码,比如
std::vector<std::string>, std::vector<int>,编译后会产生两份代码,在VC2008下,每份代码大约是3-4kb,这是因为vector比较简单代码少,如果是map则会产生30-50kb的代码,因为map里有个复杂的红黑树。对于数据处理类的代码里一般会定义很多种不同的结构体,不同的结构体放到不同的容器里,就会实例化出很多个类的代码,我见过一个项目里,这样的vector就有数百个。

2. 内存使用效率问题 (以vc++2008为例)
stl在内存使用效率上是比较低效的,比如std::string,它的sizeof大概是28,因为它有一个内置的16字节数组,用来做小字符串优化的,就是说低于16字节的字符串都会至少占用28字节内存,如果刚好17字节字符串,则会占用28字节+额外分配的字符串内存,额外分配的内存是一个堆块,又有很多浪费,相比用一个char *存储字符串大约多占用了一倍内存。
还有map<>,每一个map的node都是一块独立分配的内存,如果是 map<int, int>呢,那就很悲剧了,为了存一个int要消耗几十个字节,很浪费的。
如果元素数量有百万级,那么内存占用就很可观了,这种情况下建议自己实现allocator,做内存池。

3. deep copy问题
让两个容器的实例做赋值操作,看起来就一条语句,实际上容器里的每个元素都执行了一次赋值操作。如果容器里有百万级的数据,那么一个等号就产生了几百万次的构造和析构。
传递参数的时候一定要用 const 引用,赋值可以用 swap代替。

4. 隐式类型转换
比如 有个函数
void doSomething(const std::string &str);
调用的时候 
doSomething("hello");
能编译执行,但是会产生一个临时的匿名的std::string实例,把"hello"复制一遍,然后在调用完成后析构掉。如果这个发生在循环体内部有可能影响性能。

以上这些问题,在小程序里或者数据规模不大的时候,比如容器内元素只有几千这个规模,都不是什么大问题,那时开发效率才是重点,但是一旦有大数据stl容器会成为性能瓶颈的。

我并不是主张不用STL,而是要充分了解STL的优缺点,根据应用场景做选择。

***********************************************************************************************************************************************************

最初开始禁用 C++ STL,更多地是早期项目编码实践中留下的惯例,被后来的程序员继承下来。老项目中这种选择尤其地多。不过如果有人将其上升到公司行为在不同项目中全面禁用 STL,则没有必要,而且我倾向于做这种决定的人并不理解 C++ 编译系统。

一般来说,项目中禁用 C++ 多见于两种具体场景:或者项目的产出产品为函数库,或者需要引用第三方函数库。具体地来说,有三个主要原因:

第一个原因是二进制边界混乱。对需要在项目中使用第三方函数库的程序员来说,二进制边界是个头痛的问题。C++ 在这一方面本身就处理得不算好,加上模板后起到的是雪上加霜的后果。没有经验的程序员会贪图方便而在公开头文件中使用 C++ 模板,如果这时调用方的编译器选项设置或 STL 版本和编译方不同,那么就可能出现同样的头文件在不同的环境下二进制布局不符的情况。——顺便说一句,在过去十年里,各个主流编译器附带的 STL 版本变化节奏不慢,所以这种由于编译环境不同而导致的 bug 并不算罕见,但缺乏汇编知识的用户难以排查。

第二个原因是不愿使用异常。如今除了 Android 上的 STLPort 关闭异常,大部分主流 C++ STL 实现里都无法脱离异常使用 STL。异常带来的问题主要是两个:性能下降,代码膨胀。这几年 C++ 编译器在性能方面的改进很多,good path 的性能问题已经基本没有,但代码膨胀问题却没有太多改善,甚至这个性能问题的一部分解决方案就是以代码膨胀为代价。我写过一篇短文比对过 Android 上 gcc 4.6 在有无异常的情况下的汇编代码逻辑,可以看到,启动异常时生成的汇编代码量多出了相当一部分(我的例子中是 50%),用于处理各种隐含代码中的异常问题。这一条在手机系统中有时候会引起意想不到的麻烦,比如软件升级后导致 app 在低存储容量的手机中安装失败。顺便说一句,这个问题并不是 gcc 独有,clang 上生成的代码是一样的。参考:http://dummydigit.net/posts/2014-01-01-23-30-1.html

最后一个原因是 C 兼容。严格地说,STL 在这个问题上算是躺枪,这个坑在很多具体的场景中也是因为异常而引入,但这个问题的麻烦程度比前两个问题更高。比如 gcc 在编译纯 C 代码时默认关闭 -fexceptions 选项,因此这样编译出来的代码中没有异常处理相关的栈展开。如果某个 C++ 项目引用了一个第三方 C 项目,它很难确保那个 C 项目给出的二进制代码中正确进行了异常处理并保证代码服从异常安全操作。这种场景下混用 C/C++ ,就可能在抛出异常时莫名其妙地崩溃或者出现 C 代码区段中的资源泄漏,特别是 expat 那种大量利用回调的代码结构。要规避这种风险并非不可能,但需要 C 的架构部分做修改,比如使用 DOM 那种树形结构,这种做法对历史项目而言又很难办到。换言之,如果一个项目出于种种原因需要保持 C 兼容,而 STL 就属于其中一个不可控的变数,与其相信程序员不犯错,不如直接禁用更可控一些。参考:Code Gen Options

要解决二进制相关的问题很简单:整个项目的所有相关代码在同一个代码基上编译,强制打开编译选项添加异常代码,并去除一切二进制依赖。但对很多小公司来说,引入这样的系统对配置管理的要求较高。如果一部分依赖关系来自自己并不了解的第三方代码,轻易修改编译选项可能带来的风险与第三方代码库的规模成正比。退一步说,即便团队里真的有强大的配置管理工程师能够搞定一切,他们也不会有能力解决代码膨胀问题,除非他们有权决定换一个编译器。相比之下,前面朋友所说的所谓性能或者编译出错时糟糕的可读性,在我看来反倒是次要因素,而且这些缺陷都正在新的编译器中逐步得到解决或改善,比如 clang。

所以那些选择禁用 STL 的早期项目负责人,总有一些确实的理由,没有人那么别扭地想跟开发效率过不去。至于后来的人是真的仔细想过这些细节还是人云亦云,那是另一个问题。

references:

http://www.zhihu.com/question/20201972

时间: 2024-11-08 20:25:49

为何某些公司不允许使用C++ STL?的相关文章

STL学习小结

STL就是Standard Template Library,标准模板库.这可能是一个历史上最令人兴奋的工具的最无聊的术语.从根本上说,STL是一些"容器"的集合,这些"容器"有list, vector,set,map等,STL也是算法和其它一些组件的集合.这里的"容器"和算法的集合指的是世界上非常多聪明人非常多年的杰作.是C++标准库的一个重要组成部分,它由Stepanov and Lee等人最先开发,它是与C++差点儿同一时候開始开发的:一開

STL学习总结

STL就是Standard Template Library,标准模板库.这可能是一个历史上最令人兴奋的工具的最无聊的术语.从根本上说,STL是一些"容器"的集合.这些"容器"有list, vector,set,map等.STL也是算法和其它一些组件的集合. 这里的"容器"和算法的集合指的是世界上非常多聪明人非常多年的杰作. 是C++标准库的一个重要组成部分,它由Stepanov and Lee等人最先开发.它是与C++差点儿同一时候開始开发的:

我的STL学习之路

说起STL(标准模板库),相信了解C++的都不会陌生吧^_^.LZ是从大三开始学习C++(ps:不是科班出身),并慢慢接触使用STL的,在学校中使用STL比较多的情况是写数据结构代码,使用STL实现数据结构代码(我的数据结构源码),使我们专注于考虑算法思想,不拘泥于底层代码实现. 这里LZ不讲STL的具体知识,只讨论关于STL的学习和使用问题!结合LZ的学习过程,LZ觉得C++的学习(当然,这其中包括的STL)大致路线如下: 学习C++基本语法 掌握类.继承.多态等概念 理解面对对象和泛型编程思

STL 较详尽总结

STL就是Standard Template Library,标准模板库.这可能是一个历史上最令人兴奋的工具的最无聊的术语.从根本上说,STL是一些“容器”的集合,这些“容器”有list, vector,set,map等,STL也是算法和其它一些组件的集合.这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作.是C++ 标准库的一个重要组成部分,它由Stepanov and Lee等人最先开发,它是与C++几乎同时开始开发的:一开始STL选择了Ada作为实现语言,但Ada有点不争气,最后

关于 C++ STL

一.STL简介 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.它是由Alexander Stepanov.Meng Lee和David R Musser在惠普实验室工作时所开发出来 的.现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间. STL的代码从广义上讲分为三类:algorithm(算法).container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相

C/C++ 经典面试题汇总

面试题1:变量的声明和定义有什么区别 ? 为变量分配地址和存储空间的称为定义,不分配地址的称为声明.一个变量可以在多个地方声明,但是只在一个地方定义.加入extern修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义. 说明:很多时候一个变量,只是声明不分配内存空间,直到具体使用时才初始化,分配内存空间,如外部变量. 面试题2:写出bool .int. float.指针变量与"零值"比较的if语句 bool型数据: if(flag) { A; } else { B:} in

STL版本简介

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 本文的参考文献为:<STL源码剖析>侯捷 (1)HP STL:所有STL的祖先版本,由C++之父Alexander Stepanov和Menge Lee共同完成,可以公开修改但必须在所有的文件中加上HP的版本生命和运用权限声明. (2)PJ STL:继承了HP STL,由P.J.Plauger开发,被微软的Visual C++采用,存放目录为\:msdev\VC98\Include能找到STL头文件,不能公开.修改.贩卖 PJ STL. (3

C++ STL轻松导学

作为C++标准不可缺少的一部分,STL应该是渗透在C++程序的角角落落里的.STL不是实验室里的宠儿,也不是程序员桌上的摆设,她的激动人心并非昙 花一现.本教程旨在传播和普及STL的基础知识,若能借此机会为STL的推广做些力所能及的事情,到也是件让人愉快的事情. 1 初识STL:解答一些疑问 1.1 一个最关心的问题:什么是STL "什么是STL?",假如你对STL还知之甚少,那么我想,你一定很想知 道这个问题的答案,坦率地讲,要指望用短短数言将这个问题阐述清楚,也决非易事.因此,如果

C++ STL自学总结,仅供参考

本文内容,为博主在网上看到资料总结整合而来 一.stl格式简介 .stl文件是在计算机图形应用系统,来表示封闭的面或者体,用来表示三角形网格的一种文件格式.为STereo Lithography的缩写,由3D Systems公司于1987年开发而来,利用三角片离散近似表示三维模型,近年来已经成为快速原型技术领域广泛应用的文件格式和接口标准. 一个stl文件坐标必须是正数,没有比例信息,单位是任意的. 二.stl文件格式 stl文件分为ASCII明码格式和二进制格式. ASCII格式的stl结构如