我不确定这是一个有效的比较还是一个有效的陈述,但多年来我听到人们声称用C ++编写的程序通常需要比编写C语言的程序更长的时间以及编写的应用程序在C ++中,运行时通常比用C语言编写的慢 这些陈述中有没有真相? 除了从C ++提供的OOP灵活性中获益之外,是否应该从编译/执行时间的角度对上述比较进行考虑?
我希望这不会因为过于笼统或模糊而被关闭,它只是试图了解我多年来从许多程序员(主要是C程序员)听到的语句的实际事实。
答案 0 :(得分:10)
我会回答一个非常客观的问题的一个特定部分。使用模板的C ++代码编译速度比C代码慢。如果您不使用模板(如果使用标准库,则可能会使用模板),编译时间应该非常相似。
编辑: 就运行时而言,它更主观。尽管C可能是一种稍低级别的语言,但C ++优化器正在变得非常好,C ++可以更自然地代表现实世界的概念。如果在代码中表示您的需求更容易(正如我在C ++中所说的那样),编写比其他语言更好(和更高性能)的代码通常更容易。我不认为有任何客观数据显示C或C ++在所有可能的情况下都更快。我实际上建议根据项目需求选择您的语言,然后用该语言编写。如果事情太慢,请分析并继续使用正常的性能改进技术。
答案 1 :(得分:10)
相对运行时速度有点难以预测。有一次,当大多数人认为C ++完全是关于继承,并且使用虚拟函数 lot (即使它们不是特别合适),用C ++编写的代码通常会慢一点比等价的C.
对于(我们大多数人会考虑)现代C ++,反过来往往是正确的:模板提供了足够多的编译时灵活性,您可以经常生成比C中任何合理等价物快得多的代码。理论上你可以总是通过编写相当于“扩展”模板结果的专门代码来避免这种情况 - 但实际上,这样做非常罕见,并且非常昂贵。
C ++也有一种倾向,一般来说也是如此 - 例如,将数据读入std::string
或std::vector
(或std::vector<std::string>
)以便用户可以在没有缓冲区溢出的情况下输入任意数量的数据或数据在某些时候被截断。在C中,一个 lot 更常见的是看到有人只是编写一个固定大小的缓冲区,如果你输入的不止这个,它会溢出或截断。显然,你为此付出了代价--C ++代码通常最终使用动态分配(new
),这通常比定义数组要慢。 OTOH,如果你写C来完成同样的事情,你最终会编写很多额外的代码,它的运行速度通常与C ++版本相同。
换句话说,对于像基准测试和一次性实用程序这样的事情来说,写C的速度要快得多,但速度优势在实际代码中必须是强大的。在后一种情况下,你通常希望的最好的是C代码相当于C ++版本,并且非常诚实地做得很好相当异常(至少是IME)。< / p>
比较编译速度并不容易。一方面,模板可能很慢 - 至少在大多数编译器中,实例化模板非常昂贵。在逐行的基础上,毫无疑问C几乎总是比使用模板的C ++中的任何东西都快。问题在于线对线比较很少有意义 - 10行C ++可能很容易相当于数百甚至数千行C.只要你只看 在编译时(不是开发时间),平衡可能无论如何都有利于C,但肯定不几乎与最初的情况一样显着。这在很大程度上也取决于编译器:例如,clang在这方面比gcc更好地做了 lot (并且gcc在过去几年中也有很大改进)。
答案 2 :(得分:6)
只有使用某些特定于C ++的功能时,C ++与C的运行时才会受到影响。与返回错误代码和直接调用相比,异常和虚函数调用会增加运行时间。另一方面,如果你发现自己在C中使用函数指针(比方说,GTK),你已经为虚拟函数支付了至少一部分价格。并且在每次返回函数后检查错误代码也会消耗时间 - 在使用异常时不会这样做。
另一方面,C ++中的内联和模板可能允许您在编译时执行大量工作 - C的工作延迟到运行时间。在某些情况下,C ++最终可能比C更快。
答案 3 :(得分:5)
如果编译与C和C ++相同的代码,则应该没有区别。
如果您让编译器为您完成工作,例如扩展模板,则需要一些时间。如果您在C中执行相同操作,使用剪切粘贴或某些复杂的宏,则会占用您的时间。
在某些情况下,模板的内联扩展实际上会导致代码更专业,并且比等效的C代码运行更快。像这里:
http://www2.research.att.com/~bs/new_learning.pdf
或者此报告显示许多C ++功能没有运行时成本:
答案 4 :(得分:2)
虽然这是一个老问题,我想在这里添加我的5cents,因为我可能不是唯一一个通过搜索引擎找到这个问题的人。
我不能评论编译速度,而是评论执行速度:
据我所知,即使你不使用它,c ++中只有一个功能可以降低性能。这个特性是c ++异常,因为它们阻止了一些编译器优化(这就是为什么在c ++ 11中引入noexcept
的原因)。但是,如果使用某种错误检查机制,则异常可能比返回值检查和批量if else
语句的组合更有效。如果您必须将错误升级到堆栈中,则尤其如此。
无论如何,如果你在编译期间关闭异常,c ++不会引入任何开销,除非你故意使用相关功能的地方(例如,如果你不使用虚函数,你不必为多态付费),而大多数功能根本没有引入运行时开销(重载,模板,命名空间aso)。 另一方面,c ++中大多数形式的通用代码将比c中的等效代码快得多,因为c ++提供了内置机制(模板和类)来完成此任务。一个典型的例子是c的qsort vs c ++的std :: sort。 c ++版本通常要快得多,因为在排序中,使用的比较器函数在编译时是已知的,它至少通过函数查找来保存调用,并且在最好的情况下允许进行大量额外的编译器优化。
话虽如此,c ++的“问题”在于,很容易隐藏用户的复杂性,以致看似无辜的代码可能比预期慢得多。这主要是由于运算符重载,多态和构造函数/析构函数,但即使对成员函数的简单调用也会隐藏传递的this
- 指针,该指针也不是NOP。
考虑运算符重载:当你在c中看到*
时,你知道(在大多数架构上)一个廉价的汇编指令,在c ++中另一方面它可以是一个复杂的函数调用(想想矩阵乘法) )。这并不意味着,您可以更快地在c中实现相同的功能,但在c ++中,您不会直接看到这可能是一项昂贵的操作。
析构函数是一个类似的情况:在“现代”的c ++中,你很难看到任何通过删除的显式析构,但任何超出范围的局部变量都可能触发对(虚拟)析构函数的昂贵调用,而没有一行代码表明这一点(当然忽略}
)。
最后,有些人(特别是来自Java)倾向于编写具有大量虚函数的复杂类层次结构,其中每次调用这样的函数都是隐藏的间接函数调用,这很难或不可能优化。
因此,如果程序员不知道这些“易于使用”结构的成本,那么从程序员那里隐藏复杂性通常是一件好事,它有时会对运行时产生负面影响。
作为总结,我想说,c ++使没有经验的程序员更容易编写慢速代码(因为他们没有直接看到程序中的低效率)。但是c ++还允许优秀的程序员比使用c更快地编写“好”,正确和快速的代码 - 这使他们有更多时间在必要时考虑优化。
P.S .:
我没有提到的两件事(可能是其中我简单忘记的)是c ++能够进行复杂的编译时计算(感谢模板和constexpr)和c的restrict关键字。这是因为在时间关键程序中没有使用它们,所以我不能评论它们的一般用处和现实世界的性能优势。
答案 5 :(得分:-2)
C语言应用程序的编译和执行速度比C ++应用程序快。
C ++应用程序在运行时通常较慢,并且编译速度比C程序慢得多。
看看这些链接: