4

C++ 编程语言是否存在已知代码比等效 C 语言慢的方面?显然,这将排除 OO 特性,如虚拟函数和 vtable 特性等。

我想知道,当您在延迟关键区域(并且您不担心 OO 功能)进行编程时,您是否可以坚持使用基本的 C++ 还是 C 会更好?

4

7 回答 7

5

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

对于具有相同语义的有效 C 和有效 C++ 的给定代码构造,没有根本原因为什么两者都应该比另一个更快。但是,如果编译器的开发人员更聪明一点,一个可能会比另一个更快。

于 2012-09-11T21:29:34.257 回答
3

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

  • 在实践中很少见从中受益restrict,但它确实发生了,
  • 在很多情况下,C++ 或 C 编译器可以推断(在内联之后)restrict应用的必要条件,并采取相应的行动,即使没有使用关键字,
  • 同样是 C 编译器的 C++ 编译器可能会提供restrict__restrict作为扩展提供。

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

您是否“计算”这在一定程度上取决于您认为“等效代码”的内容。restrict永远不会改变有效使用它的程序的含义——编译器可以自由地忽略它。因此,将使用它的程序(对于 C 编译器的眼睛)和不使用它的程序(对于 C++)描述为“等效”并不是一件容易的事。这个版本restrict花费了更多(也许只是稍微多一点)程序员的努力来创建,因为程序员在使用它之前必须确保它是正确的。

如果您的意思是,是否有一个程序既是有效的 C 又是有效的 C++,并且在两者中具有相同的含义,但是实现在某种程度上受到 C++ 标准的限制,使其运行速度比 C 实现慢,那么我很确定答案没有”。如果您的意思是,标准 C 中是否有任何潜在的性能调整,但标准 C++ 中没有,那么答案是“是”。

您是否可以从调整中获得任何好处是另一回事,通过两种语言提供的不同优化,您是否会以相同的努力获得更多好处是另一回事,以及任何好处是否足以让您选择语言上还是另一种。在 C 和 C++ 代码之间进行互操作非常容易,因此如果您有任何理由更喜欢 C++,那么就像任何改变您首选编码方式的优化一样,切换到 C 通常是您在分析器告诉您时会做的事情你你的功能太慢了,之前没有。

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

同样,它可能取决于您所说的“等效”代码的含义——如果我必须使用非标准编译器(例如)编译我所谓的“标准 C++ 程序”g++ -fno-exceptions以“证明”C++ 代码是和 C 一样好,那么从某种意义上说,C++ 标准让我付出了一些代价。

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

于 2012-09-11T22:00:22.867 回答
3

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

于 2012-09-11T21:35:23.717 回答
2

与许多 C 程序员喜欢的想法相反,人们通常可以在 C++ 中编写更紧凑、更快的代码,而无需在设计上做出大量牺牲。

我想不出 C++ 中的任何东西都比 C 中的对应物慢。不排除虚函数。

于 2012-09-11T21:36:29.440 回答
1

延迟关键意味着尽可能快,还是仅仅意味着一切都必须在可预测的时间内运行?

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

但是您比 C++ 获得的是更高的抽象级别,并且您不会遇到 C 风格的错误(比如malloc()没有相应的典型错误free()

于 2012-09-11T21:34:29.193 回答
0

C++ 中没有与 C 中直接等效的代码更快——或者实际上更易于维护。

于 2012-09-11T21:54:56.257 回答
0

如果您使用的语言是 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++ 程序员的很多批评......

于 2012-09-12T00:45:15.717 回答