C比C ++快得多[关闭]


81

据我了解,所有脚本语言和核心科学程序通常都是用C编写的;这使实现变得凌乱而又直截了当。

我知道这些人想最大限度地发挥他们的性能,但是使用C字符串和C结构与使用C ++类之间确实存在区别。C ++似乎以相同的方式工作,除了虚函数外,它还存储一个类函数一次,并且该类的每个实例都调用该函数。

是什么使C更快,并且在必须是最快的项目(例如python或sqlite)中有显着区别吗?


8
“您只应根据自己面临的实际问题提出切实可行的问题。” -stackoverflow常见问题解答。
RedGrittyBrick

4
@Will-否。“一种语言比另一种语言快”是无法回答的。语言不是很快,只有它们的实现。“一种语言的X实现比另一种语言的Y实现快吗?” 通过配置文件可以回答问题,但是您要介绍什么?语言实现在各个领域中可能是快速的,也可能是缓慢的,毫无疑问,不可能对它们进行测试。一个更好的问题是“语言设计者为什么选择X语言而不是Y语言?” 这有一个明确的答案(不同语言设计者给出的理由),并且很有可能会有所帮助。
克里斯·卢茨

3
在C和C ++中,相同的代码通常应以完全相同的速度运行,不同的是,由于别名规则等的不同,具有不同语义的代码也是如此。区别在于C习语和C ++习语之间。如果您使用C或C ++的最佳实践C惯用语编写代码,则与使用最佳实践C ++惯用语编写的类似功能(无论是否编写)相比,它通常会更轻松,更快速(并且处理的失败案例更少)。 (在C或C ++中),但编写代码可能会花费很多工作。
R .. GitHub停止帮助ICE,

7
C的整体学习速度要比C ++快;)
fredoverflow

2
@Gracchus我们在这里谈论两件事。借助标准容器,RAII和诸如此类的工具,在C ++中完成常见任务要容易得多。我只是说语言本身比C大得多。如果您的目标是全面学习C ++,以便可以接受他人编写的任意C ++程序并理解它们,那么这需要几年的时间(大约学习C ++的10条)。在另一方面,学习C的所有复杂也许需要几个星期或几个月的顶部,因为根本不是在C.多语言的复杂性
fredoverflow

Answers:


63

C ++通常用于科学程序。C在该领域的流行可能正在减弱。Fortran仍然是一种流行的“低级”语言。

在C ++中,“您只为使用的东西付费”。因此,没有什么比这慢的了。特别是对于科学程序,表达式模板使使用模板引擎执行某些自定义优化来处理程序语义成为可能。

之所以选择C之类的项目是因为诸如Python之类的项目,是因为很多人(相对)完全理解C,因此大型代码库不会混淆大量贡献者中的许多人。

SQLite要求可执行代码小,而C确实有一点优势。明智地使用C ++仍然可以在嵌入式应用程序中使用,但是由于担心有害的语言功能会逐渐普及,因此C ++的使用率较低。


9
请注意,C ++确实命名了重整,而C没有重命名,这使得其他语言更容易直接与C交互。(Swig在为C ++库创建python包装器之前实际上为您构建了C ++代码的C接口。)
Sam P

7
@SamP C ++具有禁用名称修饰的功能extern "C"。Swig碰巧将C用作通用语言,但是您可以在C ++的C兼容子集中实现该包装,而无需调用C编译器。
Potatoswatter

26

我认为,原因与性能无关,而与互操作性无关。C ++语言比C语言更复杂,但是从性能的角度来看,这两种方式都没有明显的区别。一些C ++构造比C等效构造要快(比std::sortqsort),并且可能有很好的示例来说明这种情况。

编辑:在互操作性方面...

基本上,C ++标准并未定义使用不同编译器/版本创建的二进制文件之间轻松实现互操作性所需的某些内容。这里最值得注意的问题是二进制文件中符号的命名约定。在C语言中,该语言定义了从代码中的每个符号到二进制符号名称的单个映射。被调用的函数my_function将在被调用的二进制文件中创建一个符号(在二进制文件中my_function。另一方面,由于函数重载等功能,C ++函数的名称必须为错位(在二进制文件中转换为不同的函数符号,对参数的类型和返回类型进行编码),并且该标准未定义操作的方式。反过来,这意味着可以根据编译器将C ++中的同一函数编译为不同的符号(除非extern "C"用于强制C ++中的这些函数实现C互操作性)。

归根结底,脚本语言和本机代码之间的接口无论如何都必须是C接口,即使内部如何实现的细节可能是C / C ++ /任何其他本机语言。

(我故意不想激起语言优势的战争,C ++确实很强大,但是它也比C语言复杂得多,因为它比C语言复杂得多,有些看起来简单的事情可能会对它产生影响。性能)


1
我想也许可以自信地说,现代的,惯用的C ++需要一个智能的编译器才能充分利用内联,RVO,常量折叠等优点。因此,重量级C ++构造根本不可能引起人们的注意。机的水平,但良好的编译器是远对于C更加重要++比C.
Kerrek SB

@Kerrek SB:大多数现代C ++编译器(现代意味着最近几年)确实擅长识别惯用的C ++结构和优化。该std::sort就是这样一个例子:在std::less默认情况下使用仿函数并不比同等的C函数效率不高,但我知道所有的编译器将内联它(作为一个模板,它可用于内联),并删除所有的函数调用到的compare仿函数。
大卫·罗德里格斯(DavidRodríguez)-dribeas 2011年

有趣的是,Electronic Arts的EASTL库的部分理由是声称他们发现GCC在内联方面很糟糕(而MSVC则更好),因此标准库会产生太多未优化的函数调用。在EASTL中,他们使用更少的间接方法来解决此问题。谁知道当今的推理能力如何?
Kerrek SB 2011年

12

正如Bjarne在[D&E]中提到的那样,有效性是C ++的主要目标之一。因此,仅当程序员使用其“额外”功能(例如您提到的虚拟功能,rtt信息等)时,C ++的速度才会变慢

因此,我认为这更多是出于心理原因-使用C语言是因为它不允许“缓慢的” C ++功能。


9

语言并不是天生就快或慢,解释器和编译器可能会或多或少地提高效率。

除此之外,高级语言还提供通常具有运行时成本的抽象层。如果您不使用它们,则编译器可能会足够聪明,可以将它们剔除,但如果该语言的语义不允许安全地执行此操作,则可能无法实现……如果您需要它们,请自己实现使用较低级别的语言可能会比使用“慢速”语言慢。


24
除非您编写出真正糟糕的编译代码,否则脚本语言从
本质上讲

2
@ Will03uk-是什么让您无法编写通常采用脚本语言的编译器?
克里斯·卢兹

5
@Chris那就不是脚本语言了;脚本语言的含义是它是已解释的或已编译的字节码。一旦你编译它,是不是编译语言
Will03uk

1
这不是全部事实:语言语义确实很重要,因为它们确定了优化器可用的信息,并且可以安全地做出哪些假设而不必执行整个程序分析。restrict恰当的例子:使用C或luajit的关键字-仅仅因为Mike是一个聪明的人,而且因为Lua的语义非常干净(与JavaScript相比),后者不会使其他所有vm的动态语言失去活力。
Christoph

1
@Christoph我想说的是没有灵丹妙药。如果您需要动态调度,虚拟调用,代码热加载或鸭子输入等功能,那么一种开箱即用的“慢速”语言可能比C语言中的幼稚实现更快
。– fortran
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.