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