`

不得不看的两次从C++回归C的高手评论C++

 
阅读更多
转自: http://developer.51cto.com/art/200709/55858.htm

Linux之父炮轰C++:糟糕程序员的垃圾语言

Linux之父话糙理不糙 不得不看的两次从C++回归C的高手评论C++ C语言是否该扔进垃圾桶
为什么每个程序员都应该学习C语言? 每个程序员都应该学习C语言?我可不这么认为 C语言已经死了,5个需要忘却它的理由
用C设计 用C++编码
为什么使用C++
C++0x:崭新的C++,还是另一个Java?
编程语言的三大定理 动态语言为何难堪重任 动态语言面面观
【引自云风的博客】首先,给不熟悉我的朋友做一个技术背景的自我介绍:

我不是一个Linux的fans,虽然我今天对Windows也没有什么好感,但我的大部分工作还是在Windows上做应用软件开发的,对Windows还算熟悉。现在我也用非Windows的系统,但那是一台FreeBSD的机器,不是Linux。

我自认为对C++相当熟悉,精读过市面上能买到的关于C++的大部分书籍,像D&E of C++这样的经典还读了不只一遍。用C++写过至少数十万行代码,阅读过STL的大部分源码,和ACE/Boost的一小部分。

曾经我是C++的忠实粉丝,如果谁说C++的不是,要么会选择跟他辩论到底,要么会对此人不屑一顾。

还有一点我认为非常重要:我第一次爱上C++是15年前(1992年),然后对其慢慢冷淡,回归C的怀抱。而到了2000年,我又一次爱上C++。也就是说,从热爱C++到否定它,在我的个人经历中,有过两次。不排除未来有第三次的可能,但这一点足可说明,否定C++是出于一种理性的判断,而不是一种冲动。

写上这些,并非是想倚老卖老。我知道,想骂我的C++程序员,更讨厌有人倚老卖老的数落C++的不是。而且论资格,我顶多及的上Linus之父的一个零头,既然有老人在前撑腰,下面说话的底气就可以足一些了:)

C是C++的一个子集(从C99开始已经不是了),用C能写出来的代码,C++一样可以写出来,然后可以完成的更好。

这是新手们自以为是的攻击武器。Linus用了一个很恰当的理由做出反击:“你当然可以用任何语言编写糟糕的代码。但是,有些语言,尤其是带有一些心智(mental)包袱的语言本身就非常糟糕。”

没错,我最想说的就是这个。C++就是一个“带有一些心智(mental)包袱的语言”。这对软件设计的影响非常之大,没有经年的软件开发实践很难理解这一点。

从这一点上展开,把ASM和C比较的问题和C与C++的比较相提并论就没有意义了。

接下来要找到的问题要点就是,C++比C多出来那些东西后,真的会带来心智包袱吗?这个问题不好回答。单纯从C++语言特性的繁杂导致的不易掌握和误用这些角度是很难说服我自己的,更别说去说服那些比我聪明的多,刻苦的多的C++程序员们。我自认为对所谓C++的高级特性掌握的还是不错的,并运用在诸多实际项目中。他们相当有趣,在某种程度上也非常的有效。代码可以获得相当高的执行效率,并可以缩短编码的时间(更少的点击数),完成他们也有很大的成就感。

好了,让我再引用Linus的一句说到我心坎里的话。“字符串/内存管理根本无关紧要。这不是重要的部分,而且也不复杂。唯一真正重要的部分是设计。”

设计!这才是重中之重。

如果要说,这最近10年的程序员生涯我学会了什么?我认为,我比以前能设计出更好的代码了。能更准确的把握设计的坏味道。而对编程语言的掌握,对操作系统的熟悉,工作相关知识的了解等等。那些只是自然而然发生的事,那些是知识的积累,而非能力的提高。

“抽象”,“面向对象”,“设计模式”,这些重要吗?重要。对软件开发相当重要。但重要不是必要,执迷于“抽象”会使你离目标越来越远。当我们一次又一次的提取出事物的共性,建立起抽象层的时候,我们可能丢弃了真实。C++继承了C语言中“信任程序员”这一设计哲学,致力于让程序员在建立抽象层时,可以不做出额外的消耗。他的解决方式是提供尽可能多的语言工具和设计选择,任何一个都允许你在不用的时候不带来额外的性能损失。

这是一个美好的愿景:C++程序员指望可以建立强大的可复用的抽象层,面对世界上一切的具体应用。同时CPU执行序列在穿越这个坚厚的抽象层的过程中,居然可以以光速通过(通过抽象层没有额外的执行效率付出)。为此:C++社区创造了STL,创造了Boost。它们共同的关键词是:效率、复用。

再往上呢?另一个问题产生了:“——低效的抽象编程模型,可能在两年之后你会注意到有些抽象效果不怎么样,但是所有代码已经依赖于围绕它设计的‘漂亮’对象模型了,如果不重写应用程序,就无法改正。”这一段依旧是Linus语,我不停的引用,是因为我明白这一点,但是不能表达的更清楚。

使用C++的程序员不断的强调复用性,却不断的需要重写代码。如果一段代码可以不被重写,那多半是因为对重写工程量的妥协。是的,其实我们可以用C++的各种特性写出更好,更漂亮,更高效的代码。两年前的框架不那么完美,不是C++语言的错,是两年前的我能力有限的缘故。但是因为需要改写的是设计框架,这意味着我们必须跟着变更已经完成的功能模块,或是加上桥接层。

的确,STL和Boost都是世界顶尖程序员完成的。代码质量非常的高(当然,我对Boost的一部分持保留意见)。我不拿编译器兼容性和可移植性或是编译速度说事,虽然这些的确是现实问题,但不足以成为反对C++基础类库的理由。

好好的用好C++当然得用好STL,Boost也应该认真考察一下。能够仔细读一下源码更好。合格的C++程序员应该做这个。否则作为C++程序员你就违背了C++语言的设计哲学:C++信任了你,你就该对的起这种信任,搞清楚你写的每一行代码背后,机器都去干了什么。

但是,STL过于庞大了,Boost更加是。我不是抱怨阅读和学习它们的源码的难度和需要的时间和精力。正相反,我在学习它们的过程中充满了乐趣和感激之情。高手前辈透过这些高质量的代码教会了我很多东西。我隐隐担心的是,这么庞大的代码,它的设计不可能是永远正确的。两年之后,他们的设计肯定依旧正确,再两年还是的。但是我几乎敢肯定,放之更长远的时间来看,绝对会在某些设计领域发现其不是最佳的选择。到那一天,我们会选择修改吗?我想C++社区会被迫选择妥协。但是,C++程序员心中会充满痛苦。

C在这个问题上的抉择是不一样的。在效率问题上,C程序里最令人担心的是函数调用的消耗。C++程序员最津津乐道的案例就是std::sort全面击败了C库中的qsort。C语言的失败正在于多余的函数调用消耗。

但是,从一开始C就选择了承认函数调用的消耗,而这一点几乎是唯一。付出了这个代价后,设计失误导致的效率下降问题几乎总可以避免。C和C++都可以选择重写设计失败的部分,但不一样的是,C程序员几乎可以不考虑妥协的问题。同样的是考虑极端效率的语言,C语言坦然面对缺陷,才是真正的符合了KISS原则。

我对这个问题的见解,可以再引用Linus的一段话作为收场。“如果你想用更花哨的语言,C++绝对是最糟糕的选择。如果想要真正的高级特性,那就选择有垃圾回收或者好的系统集成的,而不是既缺乏C的简约(sparseness)又缺乏C的直接而且没有重要概念的高层绑定(high-level bindings to important concepts)的东西。”。这是我最近几年来一直坚持的观点:C++的发展,一定要补充对GC支持所需要的特性。

强调一下,我并不讨厌C++。

ps.最近两年多,我在做一个游戏引擎的项目。这个项目现在是第三个版本了。第一个版本是用C++实现的,但是没有用任何已存在的类库(包括STL)。在第二个版本中,我去掉了所有使用C++高级特性实现的部分,只使用了C++基本特性实现所有。07年重写的第三个版本,全部换成C代码了。这个项目的发展,可以反应出我个人对C/C++理解的心路过程。
分享到:
评论

相关推荐

    C++C++C++C++C++C++C++

    C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++

    从C语言转C++简明教程

    在编程世界中,C语言和C++是两个广泛使用的编程语言,它们各有特色,但C++作为C语言的超集,提供了更多的高级特性。本文档“从C语言转C++简明教程”将引导你从熟悉C语言的基础出发,逐步过渡到掌握C++的核心概念和...

    C C++ 库函数 C语言 C++语言 编程 初学者

    在编程世界中,C和C++是两种非常重要的编程语言,尤其对于初学者而言,掌握它们的基本库函数是至关重要的。这些语言以其高效、灵活和底层控制能力而闻名,广泛应用于系统开发、游戏引擎、嵌入式系统以及各种高性能...

    C++_实现多元线性回归可任意指定几元

    本项目是用C++编程语言实现的,能够支持用户自定义回归变量的数量,从而具有很高的灵活性。以下是对这个项目的详细阐述: 首先,我们要理解多元线性回归的基本概念。在统计学中,多元线性回归模型是一个公式,它...

    C++实现线性回归

    线性回归是一种基础而重要的统计学方法,常用于预测和建模两个变量之间的关系。在本项目中,我们将探讨如何使用C++编程语言实现线性回归算法,特别地,是针对预测房价的应用场景。C++作为一门高效且灵活的编程语言,...

    c++实现c语言子集编译器

    c++实现c语言子集编译器,共有三种数据类型INT,BOOL,ARRAY;三种控制结构IF-ELSE、WHILE、FOR,产生四个表,词法分析parser.out、action.out、goto.out、四元式parser.out。

    C++笔记-适合有c语言基础-课程基础资源

    C++笔记-适合有C语言基础-课程基础资源 本资源是为具有C语言基础的学生准备的C++笔记,涵盖了C++语言的基本概念、语法、对象和类的创建、函数和操作符的使用、内存管理、输入输出流等方面的知识点。 类和对象的...

    计算机二级c++之C++与C语言的区别.pdf

    C程序员可以省略函数原型,而C++不可以,一个不带参数的C函数原型必须把void写出来。而C++可以使用空参数列表。C++中new和delete是对内存分配的运算符,取代了C中的malloc和free。标准C++中的字符串类取代了C标准C...

    C调用REFPROP,c调用c++函数,C,C++

    这通常涉及到使用C语言的函数指针或者C++的extern "C"语法,以确保C++编译器不会对函数进行名字修饰,保持与C语言的兼容性。 在压缩包子文件的文件列表中,我们看到两个文件:Main.cpp和RefpropConstant.h。Main....

    C++实现多元线性回归 可指定任意几元 训练给出回归方程式

    控制台应用程序,C++实现多元线性回归,可指定任意几元,根据给定的数据矩阵,训练给出回归方程式

    C++和C语言合集

    《C++和C语言合集》是一本涵盖了C语言与C++编程的综合资源,由知名作者徐士良编著。这个合集包含了C语言的常用算法程序集、对C++深入思考的专论,以及关于VC++编程的实用指南。通过这份资料,读者可以系统地学习和...

    C++语言对C语言的扩充(介绍C++和C的)

    C++语言是对C语言的一次重大扩展,它保留了C语言的强大低级编程能力,同时引入了许多高级特性,使得程序设计更加面向对象和模块化。本文将深入探讨C++对C语言的扩充,并对比两者的差异。 首先,C++引入了类(Class...

    c语言与c++互相调用示例

    在编程世界里,C语言和C++是两种广泛使用的编程语言,它们各有特色,但也有交集。C语言以其简洁高效、低级内存操作而著名,而C++则是在C的基础上加入了面向对象特性,提供了更高级别的抽象。当项目中既有C语言编写的...

    Visual+C+++编程高手

    VISUAL C++高手指导,成就编程高手

    C语言调用C++类中的方法

    在编程世界中,C语言和C++是两种广泛使用的编程语言。C++是对C语言的扩展,增加了面向对象编程的支持,而C语言则以其高效、简洁和底层控制能力著称。有时,我们可能需要在C语言项目中调用C++编写的类和方法,这种...

    C语言调C++共享库

    在Linux环境下,C语言与C++的交互是一个常见的需求,特别是在既有C代码库又有C++功能需要集成的情况下。本示例将介绍如何使用CMake构建一个C++动态库,并允许C语言程序调用该库中的函数。以下是实现这一目标的关键...

    C语言中文网C++11教程

    C++11是C++编程语言的一个重要更新,它引入了大量的新特性,旨在提升效率、安全性和可读性。以下是一些从提供的压缩包文件名中提炼出的关键知识点的详细解释: 1. **可变参数模板(Variadic Templates)**:在`9C++...

    C语言与C++区别

    C语言与C++的区别,C语言的应用及其他

    C++实现最小二乘法一元回归和多项式拟合

    在进行曲线拟合时用的最多的是最小二乘法,其中以一元函数(线性)和多元函数(多项式)居多,...此类在拟合完后还能计算拟合之后的误差:SSE(剩余平方和),SSR(回归平方和),RMSE(均方根误差),R-square(确定系数)。

    cppreference c/c++ chm 中文手册 c++11 c++14 c++17 2022最新版

    c++ c++11 c++14 c++17 c++20 c++新特性 c++ reference c++参考手册 c++离线手册 最新版 cppreference.chm c++ 开发者必备 原版代码排版宽度小,阅读不方便 改成了自己喜欢的字号排版,阅读更舒适。 感谢...

Global site tag (gtag.js) - Google Analytics