尽管人们似乎喜欢抱怨C++,但我找不到为什么你会选择C而不是C++的证据。C似乎没有受到太多批评,如果C++存在所有这些问题,为什么不能将自己限制在C子集中?你有什么想法/经验?
尽管人们似乎喜欢抱怨C++,但我找不到为什么你会选择C而不是C++的证据。C似乎没有受到太多批评,如果C++存在所有这些问题,为什么不能将自己限制在C子集中?你有什么想法/经验?
Joel的回答对于你可能必须使用C的原因是很好的,不过还有一些其他理由:
然而,在某些情况下,您可能想使用C而不是C ++:
您希望获得汇编的性能,但不想编写汇编代码(理论上,C ++能够实现“完美”的性能,但编译器没有像优秀的C程序员那样看到优化)
您编写的软件非常简单或几乎可以忽略不计 - 使用小型C编译器,编写几行代码,编译即可 - 无需打开具有帮助器的大型编辑器,无需编写几乎为空和无用的类、处理名称空间等。您可以使用C ++编译器完成几乎相同的事情,并仅使用C子集,但即使是对于微小的程序,C ++编译器也更慢。
您需要极高的性能或小代码大小,并且知道C ++编译器实际上会因库的大小和性能而使其更难实现。
您认为只需使用C子集并使用C++编译器进行编译,但您会发现如果这样做,根据编译器的不同,结果会略有不同。
无论如何,如果您这样做,就是在使用C。您的问题真的是“为什么C程序员不使用C ++编译器?” 如果是这样,那么您要么不理解语言差异,要么不理解编译器理论。
我喜欢极简主义和简约风格。
害怕性能或膨胀不是放弃C++的好理由。每种语言都有其潜在的缺陷和权衡 - 好的程序员了解这些并在必要时开发应对策略,而糟糕的程序员则会遭受失败并责怪语言。
在许多方面,解释型Python被认为是“慢”语言,但对于非平凡任务,熟练的Python程序员可以轻松地编写比经验不足的C开发人员执行更快的代码。
在我的行业中,即视频游戏领域,我们通过避免在内部循环中使用RTTI,异常或虚函数等东西来编写高性能的C++代码。这些可能非常有用,但会带来性能或膨胀问题,因此最好避免。如果我们再进一步完全转向C,我们将获得很少的收益,并失去C++最有用的构造。
更喜欢C的最大实际原因是,它比C++更广泛支持。有许多平台,特别是嵌入式平台,甚至没有C++编译器。
还有供应商的兼容性问题。虽然C具有稳定且定义明确的ABI(应用程序二进制接口),但C++没有。由于vtable和constructurs / destructors等原因,C ++中的ABI更加复杂,因此每个供应商甚至版本的供应商工具链都实现不同。
从实际角度来看,这意味着您无法使用一个编译器生成的库并将其与来自另一个代码或库的二进制库链接起来,这为分布式项目或二进制库的中间件提供者创造了噩梦。
我的观点是:为什么要使用C++而不是C?
书籍《C程序设计语言》(K&R)明确地告诉你如何在不到300页的篇幅内掌握语言的所有技能。它是极简主义的杰作,没有任何一本C++书籍可以与之媲美。
显然的反驳是,大多数现代语言都具备相似的特点--它们也无法用几百页的篇幅讲清楚所有内容。这是事实。那么为什么要选择C++呢?因为它更丰富吗?更强大吗?如果您需要更多的功能或更强大的功能,请选择C#,Objective C,Java或类似的其他语言。为什么要担负C++的复杂性?如果您需要C++提供的控制程度,我认为应该使用C。C可以做任何事情,而且做得很好。
我选择使用C语言编写程序,因为我喜欢使用一种小巧而紧凑的语言。我喜欢有一种标准,可以在合理的时间内阅读(对于我来说--我是一个非常慢的读者)。此外,我还用它编写嵌入式系统的软件,这些系统很少有理想的C++编译器存在(例如某些 PIC微控制器)。
我习惯于使用C++来进行我的项目开发。后来我得到了一个工作机会,需要使用纯C语言(一个20年历史的、文档质量不佳的杀毒软件代码库...)。
C语言中我喜欢的三点是:
没有隐式操作:你能够清楚地看到你的程序究竟做了什么或者没做什么。这让调试更简单。
缺少命名空间和重载可以成为优势:如果你想知道某个函数在哪里被调用,只需在源代码目录中使用grep(命令行文本搜索工具),就可以找到它。无需任何其他特殊工具。
我重新发现了函数指针的强大功能。基本上它们允许你执行所有C++中的多态操作,而且它们更加灵活。
void*
导致了问题。有许多防御性编程技术可以保护免受错误的影响:在每个地方添加asserts断言、在结构体中增加魔数(在调试构建中)等等。但现在我们有valgrind、dr.memory,甚至MSVC工具来检测问题,因此内存损坏问题很容易解决。 - Calmariusvoid*
强制转换为 whatever*
是编译器信任的一种做法。我希望我的编译器不相信我,并有可能强制执行健壮的类型检查。C++ 编译器发出的模板替换错误很难读懂,但至少垃圾代码不会编译。 - gd1void*
通常可以避免使用。添加自定义行为的典型模式是传递函数指针和一个void*
用于用户数据。通用接口通常如下所示。然后库将此void*
传回给您的回调而不进行任何其他操作。大多数情况下,您没有任何额外的数据,因此传递NULL,并在回调中忽略用户参数。我假设您已经知道这一点。 - CalmariusLinus对你的问题的回答是"因为C++是一种可怕的语言"
他的证据充其量只是一些轶事,但他说得有道理...
C++更多地是一种低级语言,你可能更喜欢它而不是C ++ .. C ++是带有额外库和编译器支持的C语言(两种语言都具有另一种语言没有的功能,并且以不同的方式实现),但如果你有时间和经验使用C,则可以从额外添加的低级相关功能中获得益处... [编辑] (因为你习惯于手动完成更多的工作,而不是从语言/编译器本身获得某些能力)
添加链接:
我会谷歌这个问题.. 因为网络上已经有很多评论了
编译时间过长可能非常烦人。使用C++,您可能会面临非常长的编译时间(这意味着,在 Stack Overflow 上浏览网页的时间会更多!)。