什么事情(或在什么情况下)可以使C++比C慢?

use*_*288 14 c c++ polymorphism virtual exception

这是一个面试问题,面试已经完成.

什么东西可以使C++比C慢?

面试官问得很深,每当我说些什么时总是问"别的什么?".

我的想法:

C中没有的C++功能可能会有一些成本.

例如,如果我们使用赋值来在构造函数内初始化类的成员而不是初始化列表,则可以在构造函数的主体之前调用成员的默认构造函数,然后通过赋值消除该值.

需要通过搜索虚函数指针来调用虚函数.这是一个开销.

有更好的想法吗?

任何帮助将不胜感激.

谢谢 !!!

R..*_*R.. 25

C++与C相比没有什么本质上更慢的速度,但是惯用的C++代码往往比执行相同任务的惯用C代码慢得多,也更重.惯用这个词在这里是关键; 如果您编写C代码来执行任务的方式与在C++中执行该任务的方式完全相同,那么它将同样缓慢.另一方面,如果您知道隐藏成本通常会在C++中出现的地方,那么您可以尽量减少C++的成本并获得C++的好处而不需要花费很多成本.

首先是动态内存分配.在C中,您可以看到您所做的每一点动态内存分配,因为它都是显式的(以调用malloc或调用返回已分配对象的第三方库函数的形式).在C++中,由于隐藏的分配在其构造函数中发生,因此对象的存储持续时间是自动的许多类对象仍将导致动态内存分配.一个好的C++ STL(或第三方库)实现可以通过在对象本身中包含小缓冲区来避免大量此类成本,并且仅在需要大缓冲区时执行动态分配,但实际上很少这样做.(如果我没有弄错,llvm的libc ++会这样做,但是GCC的libstdc ++没有.)因为这是一个通常不在你自己的代码控制范围内的实现质量问题,你可以做的最大限度地减少影响的是意识到自动对象分配动态内存的可能性,并避免创建超出您需要的内容(例如,尽可能使用指针或引用).这对您的代码也有其他好处.

另一个重要领域是字符串处理.在惯用语C中,字符串一举构造snprintf或类似.在C++和许多其他具有更强大的字符串类/类型的语言中,字符串的连接(逐个构造)是惯用的.这是非常低效的,导致多个分配/解除分配步骤,副本等,更不用说产生的内存碎片.我不确定C++的最佳实践是什么(我不精通C++),但应该有办法减少这种影响.

当然,最常见的是隐藏代码.这是一种全能的方式.在C++中很容易编写代码,从而可以执行许多您从未看到过的额外代码.构造函数/析构函数,重载运算符和模板是最明显的原因.同样,如果你想在C中以相同的方式做事,成本将是相同的,但不同的是,在C中,你会立即看到成本,因为你必须自己编写.

  • 顺便说一下,几乎每个实际使用`std :: string`都是不安全的,因为分配失败的异常没有得到妥善处理.你可能会称之为"只是DoS",但如果文件处于不一致的状态,它也可能导致进一步的危害.我同意你可以使它安全(在编写文件时使你的应用程序对异步终止具有强大的功能,或者正确处理异常),但如果你这样做了一万次,无论你多么有经验,你都会犯错误.看看这个论点开始有多愚蠢了? (3认同)
  • 您所要做的就是*查看界面*.通过`sizeof(src)`而不是`sizeof(dest)`你可以保证得到一个令人讨厌的问题 - 更不用说你写了十亿次来侵犯DRY的事实.或者编写格式说明符,然后在更改变量类型时不更新它.或者有太多的格式说明符.或者意外地手动覆盖NULL终止符.接口允许所有这些错误,并在真正的C程序中发生.但是,使用C++标准字符串处理是不可能*造成同等错误. (2认同)

Pup*_*ppy 12

没有.事实上,C++比C快曾经比较std::sortqsort

人们说虚拟功能需要花费时间来打电话.他们是这样.但是相当于在vtable中查找的C也是如此.如果您使用两种语言编写等效逻辑,则C++版本将更易于维护,更清晰,更快速.

编辑:哦,是的,你可以根据需要printf从C++ 调用,或者如果你愿意,可以完全重新执行流实现.

我是否提到由于错误的NULL终止符导致崩溃的程序的性能相当不重要?

宏和内联函数将像C++中的模板一样"膨胀"C可执行文件.

  • 这个答案完全错了.任何可以用模板完成的事情都可以使用内联函数和可能的C语言来完成.但更重要的是,OP问*哪些C++特性往往会使C++变慢*,如果你想编写C++,这是一个非常好的问题但是不要让你的代码在陈规定型上变得缓慢而臃肿. (8认同)
  • 我来到这里是为了给出严肃的答案,不要搞小语言战争.我不怀疑,使用足够先进的工具链和编写代码的聪明人,您可以使用C++生成快速,非膨胀的程序.但很明显,大量(我会说绝大多数)C++程序都非常缓慢和臃肿.一个很好的例子是替代malloc实现的所有工作,以弥补KDE的缓慢程度(主要是由于我在答案中解释的第一个问题). (5认同)
  • @nhahtdh人们抱怨iostream性能经常使用它错了.使用std :: endl而不是"\n"并保持流与cstdio同步是一些最常见的错误. (2认同)
  • C++本身并不比C快:C++编译时泛型通过模板不一定比C运行时泛型通过函数指针快,因为优秀的优化器可以通过函数克隆来平衡游戏领域(即创建一个具有虚拟的专用版本)电话内联); 当然,只有在翻译单元中提供该功能时才有可能:请参阅http://news.ycombinator.com/item?id=3717463了解如何获得C++ - 来自`qsort()`和https的可比性能:/ /bitbucket.org/cggaertner/listsort用于C中的自定义排序算法,它击败了`std :: forward_list :: sort()` (2认同)
  • 你关于"安全"和"不安全"的论点是偏离主题的,并且会分散注意力.面试问题不是关于语言的相对安全性(通常是夸大其词;查看JS,PHP等代码中的所有漏洞,即使它们应该是没有指针的"安全"语言).这是关于速度. (2认同)

Dty*_*ree 6

哇...在答案中对C++有很多的爱,所以我会像Devil的倡导者那样咆哮.

在原子语言规模上,我同意在C++中很少或根本没有显着"慢"执行.在更高的层面,它变得复杂.C++是一个有用的工具,但往往是华丽不停地谈论不适当地作为用于所有问题的解决方案.当我们使用最简单的语言来描述问题时,它会更好,有时候这是C++的其他时间......汇编,操作码,解释语言.

C++在很大程度上依赖编译器来"解释"意图,通过多次迭代爬行模板,类,宏等多层.通过翻译的每个循环都有可能遇到意想不到的后果规律.据我所知,处理器没有本机处理C++构造的寄存器或操作码,因此每个都必须分解为简化部分.在这方面,编译器和代码标准是王道.在某些情况下,它是教授三年级学生(处理器)的数学(编译器)PHD教师的哲学等价物.

我喜欢C++并保守地使用它,但多年来我几乎没有看到它写得很好.我想强迫一些人看一下最终由构建反刍的程序集或机器代码,直到他们理解它是多么复杂.坏C是一回事,糟糕的C++可能会呈指数级恶化.

面试的更好答案......"你的团队什么时候才能看到C++不是问题的答案?"


Att*_*ila 5

C++中的大多数功能都是解决C中(潜在)问题的解决方案(例如:构造函数,以确保创建的数据包的有效性(struct在C中)

这意味着要在C中编写一个试图避免出现C++特性问题的正确程序,您将不得不执行C++在幕后执行的类似操作.这导致两种情况下的类似性能.

当然,您总是可以编写"更快"的草率程序,但在所有情况下都无法正常工作


Pub*_*bby 5

C有restrict,C++没有,尽管大多数编译器都将它作为扩展.

还有C++没有的可变长度数组.

  • 基于堆的内存竞技场可以比`alloca`分配更快. (2认同)
  • @DeadMG:取决于实施.在带有帧指针的一个上,`alloca(n)`纯粹是`__asm__ __volatile __("sub%1,%% esp; mov %% esp,%0":"= r"(结果):"g"(n ));`或等同物. (2认同)

thb*_*thb 5

有更好的想法吗?任何帮助将不胜感激.

C++中的STL很少比C中特殊编码的等价物慢.但是,STL 的便利性有时会导致编写较慢的代码.例如,假设一组固定的100个项目,其中的变量选择为10或15.假设程序的时间关键循环多次询问是否i已选择项目.支持这种时间关键循环的快速数据结构将是100个bool的阵列(或矢量等).但是,填充a std::set<size_t>可能更容易在C++中编码而不是填充数组.出于这个原因,C++程序员可能更喜欢数组上的集合.

当然,较慢的代码是否是一个问题取决于时间关键循环将看到多少服务.如果对阵列技术进行编程需要额外的半小时,并且在程序的整个生命周期内节省的总执行时间为0.5秒,则设置技术可能更可取.另一方面,如果总执行时间节省是30天,则阵列技术可能是优选的.

可以给出许多类似的答案.祝你的面试顺利.

  • 你不能有一个带有100个条目的`std :: set <bool>`.`bool`,`true`和`false`只有2个值,所以最多只能包含2个值. (3认同)