百科问答小站 logo
百科问答小站 font logo



为什么 C 语言没有被 C++ 取代? 第1页

  

user avatar   heng-xu-zhi-jing 网友的相关建议: 
      

自从STL开创了以头文件作为库的使用方式之后,C++以源代码的形式来使用库的倾向就越来越严重,boost更将此发挥的淋漓尽致。你说说,一种语言发展到只能以源代码的形式来使用库,其不得人心可想而知。是的,即便是C语言有千般不是,但是,胜在简单啊,其二进制复用的友好性,人尽皆知。任何语言,只要稍微努力一把,就可以尽情享用C的运行库。而C++的运行库,就连C++自己,用起来也是一地鸡毛。

这件事情,说起来就来气。回顾历史进程,也能理解,一句话,积重难返,但真的是不能容忍。一开始,大家并没有意识到二进制abi的必要性,等到发现其巨大深远的影响力时,一切已经回天乏术,以至于今时今日的C++在寒风中索索发抖,面临被淘汰的审判,也和这个缺陷息息相关。展开来讲的话,会涉及到很多很有意思的话题,对象的内存模型,this指针的传递,成员函数指针,多继承,异常,模板的代码膨胀以及com,简直千言万语,一言难尽。

一直以来,C++的标准委员会办事不力,心思都不在办正经事上,只管在template或者其他无关紧要(其实也不是完全没有意义)的语法糖上大做文章,经过不懈的努力,template终于成为C++相比于其他语言唯一能拿得出手的好东西,可惜这玩意太复杂,就没几只猿猴能理解透彻。每次要解决abi问题的时候,总是有一大堆借口,什么函数操作符重载了,什么多继承虚继承了,什么模板了,总之,一提abi,就想着要支持这些鬼破东西,所以就迟迟无能为力搞abi了,这辈子都不可能搞abi了。别说C++写出来的二进制组件给其他语言调用,就算是C++编译器之间想要实现二进制代码的共享,几乎不可能。哪怕是同一编译器的动态库模块调用,也都从来不轻松。

其实很多时候很多时候,绝大多数情况下,业界并不需要大而全的解决方案,只要基本能用就行,要求就一点点。祈求标准会不要因为大而全的解决方案做不出来,就连最基本的痛点从来也管都不管一下,哪怕一点点的照顾也都好啊。没有,关于abi的标准,就只是最最基本的那几条,为了兼容c结构体而存在的那几条,谢天谢地,幸好有这几条宝贵的规定,才能写跨编译器的代码。太不容易了!既然当初选择了要兼容C代码,就应该尽量保证二进制代码也与C最大程度的保持一致。标准上对C++abi的处理,简直是语焉不详到了天怒人怨的地步。C++对二进制库的复用态度,从一开始就好像从来不放在心上。

就abi而言,至关紧要的第一条,成员函数下this指针变量的传递方式,标准完全视而不见,好像这个问题完全不存在,由编译器产商自由发挥,群魔乱舞,或寄存器传递,或作为函数参数传递的第一个参数或者最后一个参数。这些乱象,各有各的好处,但是依本座看,就不必顾忌那么多,this就应该当做是函数的第一个参数来传递,没什么不好,既保证了C函数参数传递的语义,又保证了代码的高可移植性。甚至,猿猴还能玩函数指针与成员函数指针互相赋值的可能性。成员函数与非成员函数的巨大鸿沟,很大文章都做不了。

第二条,对象的虚函数表指针的位置,这个标准也没定。据本人测试,试过的几款编译器,gcc,clang,基本上都将虚函数表指针放在对象的首地址上,msvc就更不用说了。所有不这么搞的编译器,都应该打入冷宫,听说Intel好像是将虚函数表指针放在对象尾部,烧死这些异教徒,基础库也都不应该兼容这些犯贱的编译器。

至于多继承那些,这是C++特有之物,就先不必管它们,反正也没法与C兼容了。就个人而言,代码上尽量不用多继承,自从发现了C++下可以搞非侵入式的接口之后,已经很久不搞多继承了。虽然这个玩意很有用,但是业务代码是绝对不会动用多继承这个老兄的。

有了第一二条之后,再加上原来的关于对象字段内存布局的规定。要从二进制最大程度的保持与C一致,就很有希望了。接下来自然就是成员函数名字的重修饰问题了。为了支持重载,在二进制代码上,C++编译器会给函数重新起一个名字,这个名字会用到其所有参数的类型以及类名本身甚至命名空间,这也无可厚非。但是,这样一来,就导致C++下的类完全就不能给其他语言调用的一丝丝可能性了。基于此,C++给出一个新语法的注解,用来由猿猴规定这个成员函数在二进制代码的名字说明。也不一定就是这种办法,反正就是标准可以规定普通成员函数下在二进制模块中的唯一名称,以便于其他语言可以找到它们,进而进行调用。哪怕是构造函数或者析构函数,其实也都有办法开放其二进制的调用方式。异常什么的,不必担心。既然要给其他模块使用,那就保证函数不发生异常就是了。

乱七八糟说了一大堆话,总之,假如历史重来的话,C++完全可以保留现有语法特性(template,多继承,成员函数),同时又能极大程度上与C的内存布局保留最大程度上的兼容性。说不定进而可以探索出来一条写C++代码的良好风格。当然,现在说什么也已经迟了。很多事情,C++可以做得更好,可惜,为了所谓功能完备为了所谓的类型安全,搞出来很多不必要的要求,很多代码写起来也巨麻烦。

Com曾经尝试解决大C++二进制组件复用的毛病,做了很大的努力,整套规范搞得非常非常复杂。可见,C++ abi简直就是无解。对了,如果不考虑跨语言的问题,如果将com的特点只用在C++上,搭配上完备的反射,用着可以相当愉快呢,最起码的一点就是所有的接口都不必再从IUnknown上继承了,IUnknown可以不存在了。


user avatar   pjz-68-79 网友的相关建议: 
      

C语言几乎没有什么包装,完完全全把计算机暴露给程序员,用C可以精确控制计算机。每写一条C语句,资深的C程序员对生成什么汇编指令心里是有数的,访存性能如何,cache性能如何,心里都是有数的。所以用C可以写出性能逆天的程序。以我做的开源网络压测工具dperf为例。

dperf是一款性能强劲开源网络压力测试仪。性能可以达到100Gbps,每秒1千万TCP新建连接,几十亿TCP并发连接数。它不仅性能高,还能够实时准确发现网络中的丢包,非常适合测试防火墙、四层负载均衡(如LVS,DPVS、F5等),交换机,网卡、CPU、虚拟机的网络报文处理能力。

dperf是基于DPDK框架,用C语言编写,目前代码量在9千行左右,有完整的设计文档、配置手册。dperf实现了小型TCP/UDP协议栈,支持IPV4、IPV6,也非常适合学习计算机网络的朋友们拿来做实验。

dperf是Linux基金会支持的DPDK官方生态项目,是世界上性能最强的网络压测工具;进入过github C语言趋势榜;获得过世界著名项目keepalived作者Alex的点赞。进一步了解,请看附录,喜欢的话,请给TA加个star吧,谢谢!

总结一下。C的优势不在多,而在少。在编写高性能程序方面,C具有不可替代性。


附录:

ArtNowBen:dperf: 开源压力测试工具

ArtNowBen:dperf进入DPDK生态项目

ArtNowBen:dperf登上了github C语言趋势榜

ArtNowBen:dperf项目收到keepalived作者的star




  

相关话题

  学C++花了一天半刚搞懂指针和数组,怎么提高效率? 
  为什么下载的安装包都需要安装才能用,而不是可以直接用呢,安装的过程到底是在做什么? 
  你工作中最推荐的 C/C++ 程序库有哪些,为什么? 
  操作系统里面经常说的一个功能用「软件实现」还是用「硬件实现」,其本质区别是什么? 
  为什么说指针是 C 语言的精髓? 
  计算机大牛们,看C++有关书籍是不是一遍就看懂了,总感觉自己笨,有些地方需要看几遍才懂? 
  <<深度探索c++对象模型>>中的虚继承看着蛋疼,感觉这在实际中也没多大用,需要继续深究吗? 
  如果C语言程序在一台电脑上可以运行,到另外一台就运行出问题是什么原因? 
  编译器生成的汇编语句执行顺序为什么与C代码顺序不同? 
  是否有办法在malloc的hook函数中调用原生malloc? 

前一个讨论
杨-米尔斯理论(Yang-Mills theory)是什么?
下一个讨论
为什么说俄罗斯民族是战斗民族?





© 2024-05-21 - tinynew.org. All Rights Reserved.
© 2024-05-21 - tinynew.org. 保留所有权利