C++代码,它比它的C等价代码慢

C++ code which is slower than its C equivalent?

本文关键字:代码 C++      更新时间:2023-10-16

C++编程语言是否有任何方面的代码比等效的C语言慢?显然,这将排除OO功能,如虚拟功能和vtable功能等。

我想知道,当你在延迟关键领域编程时(你不担心OO特性),你是否可以坚持使用基本的C++,或者C会更好?

在C或C++语言标准中没有任何东西指定任何构造的速度(C++确实指定了应用于容器的一些操作的时间复杂性,但这超出了您的问题范围)。为给定结构生成代码的速度取决于用于编译它的编译器以及它运行的系统

对于给定的具有相同语义的有效C和有效C++的代码结构,没有基本的理由说明其中一个应该比另一个更快。但是,如果编译器的开发人员稍微聪明一点,其中一个可能会比另一个更快。

这取决于你所说的"等价"是什么意思。如果将C的stdio.h与C++的iostream进行比较,stdio.h操作通常会更快(在某些情况下会快一点)。但是,如果您谈论的是在C++的子集中编写的代码,这些代码也可以编译为有效的C,那么生成的机器代码可能是相同的。

例如,C++缺少关键字restrict。使用正确,有时允许编译器生成更快的代码。

  • 在实践中很少看到restrict的好处
  • 在很多情况下,C++或C编译器可以推断(在内联之后)restrict的必要条件适用,并相应地采取行动,即使没有使用关键字
  • 同时也是C编译器的C++编译器可能无论如何都会提供restrict__restrict作为扩展

但偶尔(或者在某些领域中很常见),restrict是一个非常好的优化,我被告知这是仍然使用Fortran的原因之一。这当然是C和C++中严格的混叠规则的原因之一,它们在更有限的情况下提供了与restrict相同的优化机会。

你是否"计算"这在一定程度上取决于你认为的"等效代码"。restrict永远不会改变一个有效使用它的程序的含义——编译器可以自由忽略它。因此,将使用它(对于C编译器来说)的程序和不使用它的(对于C++)的程序描述为"等价"并不过分。带有restrict的版本需要程序员花费更多的精力(也许只是稍微多一些)来创建,因为程序员在使用它之前必须确保它是正确的

如果你的意思是,有没有一个程序是有效的C和有效的C++,并且在两者中都有相同的含义,但实现在某种程度上受到C++标准的约束,运行速度比C实现慢,那么我很确定答案是"没有"。如果你的意思是,标准C中是否有任何潜在的性能调整,但标准C++中没有,那么答案是"是的"。

你是否能从调整中获得任何好处是另一回事,如果在两种语言中都有不同的优化,你是否能通过同样的努力获得更多好处是另回事,是否有足够大的好处可以作为你选择语言的基础也是另一回事。在C和C++代码之间进行互操作非常容易,所以如果你有任何理由喜欢C++,那么就像任何改变你喜欢的编码方式的优化一样,当你的分析器告诉你的函数太慢时,通常会切换到C,而不是以前。

此外,我试图以某种方式说服自己,假设您从未使用任何具有非平凡析构函数的类型,那么潜在的异常是否会降低性能。我怀疑在实践中它可能是可以的(这与"不用就不用"的原则相矛盾),如果只是因为否则gcc拥有-fno-exceptions就没有意义的话。C++实现降低了成本(而且它主要在rodata中,而不是代码中),但这并不意味着它是零。延迟关键码可以是也可以不是二进制大小关键码。

同样,这可能取决于你所说的"等效"代码的含义——如果我必须使用非标准编译器(如g++ -fno-exceptions)编译我所谓的"标准C++程序",以"证明"C++代码与C代码一样好,那么在某种意义上,C++标准会让我付出一些代价。

最后,C++运行时本身有启动成本,这不一定与"相同"程序的C运行时启动成本相同。你通常可以通过移除你并不严格需要的东西来降低两者的成本。但这是一项努力,实现不一定每次都能完全为您服务,所以在C++中,您不必为不使用的东西付费,这不是严格意义上的。这是一般原则,但实现它是一个实施质量问题。

与许多C程序员喜欢的想法相反,人们通常可以用C++编写更紧凑、更快的代码,而不必在设计上牺牲太多。

我想不出C++中有什么比C中的对应函数慢的了。不排除虚拟函数。

关键的延迟是否意味着尽可能快地,还是仅仅意味着所有东西都必须在可预测的时间内运行

如果是第二种情况,那么只有newdeletetry/catch不能在可预测的时间内运行。在嵌入式编程中,有一些指令可以避免此类调用。在其他情况下,尤其是在C++11中,您可能会注意到有些东西更快(std::sort比C的sort()更快),有些则稍微慢一些。

但是,通过C++可以获得更高的抽象级别,并且不会出现C风格的错误(比如典型的没有相应free()malloc()

C++中没有任何代码在C中的直接等价代码更快,或者说更易于维护。

如果您使用的语言是C和C++的交集,那么使用C编译器与C++编译器编译代码时性能的任何差异都纯粹是实现质量问题;没有理由一个比另一个快。

当然,在现实世界中,如果你使用C++,你可以使用C++在C和C++的交叉点上的附加功能进行编程,并使用与C中不同的习语。相反,如果你在使用C,你至少使用了与C++中使用的非常不同的习语,您可能还使用了C++所没有的现代C语言的其他功能,如Steve提到的restrict关键字、VLA或指向VLA类型的指针或复合文字。这些功能在某些情况下可以带来重大的性能优势,但根据我的经验,它们并不是大多数选择C而不是C++的人这样做的原因。

在我看来,主要的区别实际上是习语。在C中,习惯做法是通过将next/prev指针直接放在列表中保存的结构中来创建链表,而不是为列表和列表节点使用单独的包装器对象。在C语言中,习惯做法是将字符串的元素作为字符数组直接迭代。在C语言中,习惯做法是尽可能使用完全存在于自动存储中的对象,而不是分配动态存储。等等。这些惯用的差异是C代码比C++更快、更轻的主要方式。

当然,如果你愿意,你可以在C++中使用相同的习语,因为大多数C习语所需的大多数语言结构都存在于C和C++的交集中。然后,您还可以在适当的时候使用C++的附加功能。但是,您将编写非惯用的C++代码,并且可能会受到其他C++程序员的大量批评。。。