性能受到C ++风格的影响?

时间:2009-03-23 19:50:31

标签: c++ performance casting

我是C ++样式演员的新手,我很担心使用C ++样式演员会破坏我的应用程序的性能因为我的中断服务例程中有real-time-critical deadline

我听说有些演员甚至会抛出异常!

我想使用C ++样式转换,因为它会使我的代码更“强大”。但是,如果有任何性能损失那么我可能不会使用C ++样式转换,而是会花更多时间测试使用C风格转换的代码。


有没有人做过任何严格的测试/分析来比较C ++样式演员与C风格演员的表现?

你的结果是什么?

你得出了什么结论?

7 个答案:

答案 0 :(得分:82)

如果C ++样式转换可以概念性地替换为C样式转换,那么就没有开销。如果它不能,如dynamic_cast的情况,没有C等价物,你必须以这种或那种方式支付费用。

例如,以下代码:

int x;
float f = 123.456;

x = (int) f;
x = static_cast<int>(f);

使用VC ++为两个强制转换生成相同的代码 - 代码为:

00401041   fld         dword ptr [ebp-8]
00401044   call        __ftol (0040110c)
00401049   mov         dword ptr [ebp-4],eax

在转换为引用时,唯一可以抛出的C ++强制转换是dynamic_cast。为避免这种情况,请转换为指针,如果转换失败,将返回0。

答案 1 :(得分:39)

在运行时唯一具有任何额外成本的是dynamic_cast,其功能无论如何都无法直接使用C样式转换。所以你没有问题。

让自己放心的最简单方法是指示编译器生成汇编程序输出,并检查它生成的代码。例如,在任何理智的编译器中,reinterpret_cast将完全消失,因为它只是意味着“盲目前进并假装数据属于这种类型”。

答案 2 :(得分:16)

为什么会出现性能影响?它们执行完全与C强制转换相同的功能。唯一的区别是它们在编译时捕获更多错误,并且在源代码中更容易搜索。

static_cast<float>(3)完全等同于(float)3,并且会生成完全相同的代码。

鉴于float f = 42.0f <{1}}完全等同于reinterpret_cast<int*>(&f),并且会生成完全相同的代码。

等等。唯一不同的强制转换是(int*)&f,是的,可以抛出异常。但那是因为它做了C风格演员无法做到的事情。因此,除非您需要其功能,否则请勿使用dynamic_cast

通常可以安全地假设编译器编写者是智能的。根据标准给出两个具有相同语义的不同表达式,通常可以安全地假设它们将在编译器中以相同的方式实现。

糟糕:第二个示例当然应该是reinterpret_cast,而不是dynamic_cast。现在修好了。

好的,只是为了说清楚,这就是C ++标准所说的:

§5.4.5:

  

执行的转化      
      
  • a dynamic_cast(5.2.11)
  •   
  • a const_cast(5.2.9)
  •   
  • 一个static_cast后跟一个static_cast
  •   
  • a const_cast(5.2.10)或
  •   
  • a reinterpret_cast后跟reinterpret_cast
  •   
     

可以使用演员表演   显式类型转换的表示法。   相同的语义限制和   行为适用。如果转换可以   被解释为不止一个   上面列出的方式,解释   列表中首先出现的是   使用,即使是由此产生的演员表   这种解释是不正确的。

因此,如果任何,由于C风格的演员表是根据C ++演员表实现的,因此C风格的演员表应该更慢。 (当然它们不是,因为编译器在任何情况下都生成相同的代码,但它比C ++风格的转换更慢更合理。)

答案 3 :(得分:15)

有四种C ++样式转换:

  • const_cast
  • static_cast
  • reinterpret_cast
  • dynamic_cast

如前所述,前三个是编译时操作。使用它们没有运行时间的惩罚。它们是编译器的消息,已经声明为一种方式的数据需要以不同的方式访问。 “我说这是一个int*,但让我访问它,好像它是char*指向sizeof(int) char s”或“我说这个数据是只读的,现在我需要将它传递给不会修改它的函数,但不将参数作为const引用。“

除了通过强制转换为错误类型和数据故障(数据总是有可能使用C风格的转换)导致数据损坏之外,这些强制转换的最常见运行时问题是实际声明为const的数据可能不会可以转换为非const。将声明为const的内容转换为非const然后修改它是未定义的。 Undefined means you're not even guaranteed to get a crash

dynamic_cast是一个运行时构造,必须具有运行时成本。

这些演员阵容的价值在于他们具体说出你想要演绎的内容,从视觉上突出,并且可以用脑死亡的工具进行搜索。我建议使用它们而不是使用C风格的演员阵容。

答案 4 :(得分:4)

使用dynamic_cast时,在运行时进行了几次检查,以防止您做一些愚蠢的事情(GCC mailing list更多),一个dynamic_cast的成本取决于受影响的类数量什么类受影响等。
如果您确定演员阵容是安全的,您仍然可以使用reinterpret_cast

答案 5 :(得分:3)

虽然我同意声明“在运行时唯一的任何额外成本是dynamic_cast”,但请记住可能存在编译器特定的差异。

我已经看到针对我当前编译器的一些错误,其中代码生成或优化略有不同,具体取决于您使用的是C风格还是C ++风格static_cast强制转换。

因此,如果您担心,请检查热点上的反汇编。否则,只要在不需要时避免动态转换。 (如果关闭RTTI,则无论如何都不能使用dynamic_cast。)

答案 6 :(得分:1)

规范的事实是集合,所以试试两者,看看你是否有不同的逻辑。

如果你得到完全相同的装配,没有区别 - 没有。你真正需要坚持使用旧的C版本的唯一地方是纯C例程和库,在那里引入C ++依赖只是为了类型转换是没有意义的。

有一点需要注意的是,强制转换在一个相当大的代码片段中发生。在我的整个职业生涯中,我从未在一个逻辑中搜索“所有演员阵容” - 你倾向于搜索特定类型的演员阵容,如“A”,搜索“(A)”通常同样有效像“static_cast&lt; A&gt;”这样的东西。使用较新的强制类型转换来进行类型验证等等,而不是因为它们使搜索变得更加容易。