性能打击从C + +风格转换?
我是新来的C + +风格强制转换,我担心使用C ++风格强制转换会破坏我的应用程序的性能,因为我的中断服务程序中有一个实时关键的截止date 。
我听说有些演员甚至会抛出exception!
我想使用C ++风格强制转换,因为它会使我的代码更“健壮”。 但是, 如果有任何性能下降,那么我可能不会使用C ++风格的转换,而是花费更多的时间来testing使用C风格转换的代码。
有没有人做过任何严格的testing/分析来比较C ++风格演员的performance与C风格演员?
你的结果是什么?
你画什么结论?
如果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 ++types是dynamic_cast
。 为了避免这种情况,转换为一个指针,如果转换失败将返回0。
运行时唯一有额外成本的是dynamic_cast
,它具有无法直接用C风格转换的function。 所以你没有问题。
让自己放心的最简单方法是指示编译器生成汇编输出,并检查它生成的代码。 例如,在任何合理的编译器中, reinterpret_cast
将完全消失,因为它意味着“盲目前进并假装数据是这种types的”。
为什么会有性能问题? 它们执行与C强制转换完全相同的function。 唯一的区别是,它们在编译时捕获更多的错误,并且在源代码中更容易search。
static_cast<float>(3)
完全等价于(float)3
,并且会生成完全相同的代码。
给定一个float f = 42.0f
reinterpret_cast<int*>(&f)
完全等价于(int*)&f
,并且会生成完全相同的代码。
等等。 唯一不同的是cast dynamic_cast
,可以抛出exception。 但是那是因为它做了C风格演员不能做的事情。 所以除非你需要它的function,否则不要使用dynamic_cast
。
假设编译器编写者是智能的,通常是安全的。 给定根据标准具有相同语义的两个不同expression式,通常假设它们将在编译器中被相同地实现是安全的。
糟糕 :第二个例子当然应该是reinterpret_cast,而不是dynamic_cast。 现在修复它。
好吧,为了清楚起见,下面是C ++标准所说的:
§5.4.5:
转换执行
- 一个
const_cast
(5.2.11)- 一个
static_cast
(5.2.9)- 一个
static_cast
后跟一个const_cast
reinterpret_cast
(5.2.10),或者- 一个
reinterpret_cast
后跟一个const_cast
。可以使用显式types转换的转换符号来执行。 相同的语义限制和行为也适用。 如果一个转换可以用上面列出的多种方式解释,那么就使用列表中第一个出现的解释,即使这个解释产生的结果是不合格的。
所以,如果有的话 ,由于C风格演员实施的C + +转换,C风格演员应该更慢 。 (当然他们不是,因为编译器在任何情况下都会生成相同的代码,但比C ++风格的types转换更为合理)。
有四个C ++风格的转换:
-
const_cast
-
static_cast
-
reinterpret_cast
-
dynamic_cast
如前所述,前三个是编译时操作。 使用它们没有运行时间的损失。 它们是向编译器发送的消息,即以单向方式声明的数据需要以不同的方式访问。 “我说这是一个int*
,但让我来访问它,就好像它是一个char*
指向sizeof(int) char
s”或“我说这个数据是只读的,现在我需要将它传递给函数将不会修改它,但不会将该参数作为一个常量引用。
除了通过将数据转换为错误的types和缓冲数据(总是使用C风格转换的可能性)来破坏数据之外,这些转换最常见的运行时问题是实际声明为const
数据可能无法转换为非const。 将const
声明为非const的东西,然后修改它是未定义的。 未定义意味着你甚至不能保证崩溃 。
dynamic_cast
是一个运行时构造,必须具有运行时成本。
这些演员的价值在于他们具体地说出了你想要演奏什么,从视觉上伸出来,并且可以用大脑死亡的工具进行search。 我会推荐使用它们来使用C风格的演员。
当使用dynamic_cast
时,会在运行时进行一些检查,以防止你做一些愚蠢的事情(更多的GCC邮件列表 ),一个dynamic_cast
的成本取决于有多less类受到影响,哪些类受到影响等。
如果你确定演员是安全的,你仍然可以使用reinterpret_cast
。
虽然我同意“在运行时只有一个额外的开销是dynamic_cast
”,但请记住,编译器可能存在一些差异。
我已经看到了一些针对当前编译器提出的错误,其中代码生成或优化略有不同,具体取决于您使用的是C风格还是C ++风格的static_cast
。
所以如果你担心,请检查热点的反汇编。 否则,当你不需要时,避免dynamic转换。 (如果closuresRTTI,则无论如何都不能使用dynamic_cast
。)
规范的事实是程序集,所以试试看看你是否有不同的逻辑。
如果你得到完全相同的组件,那就没有区别 – 不可能有。 唯一需要坚持使用旧的C语言转换的地方是纯粹的C例程和库,对于types转换而言,引入C ++依赖是没有意义的。
有一件事要注意的是,在一个体面大小的代码片段发生施放。 在我整个职业生涯中,我从来没有在逻辑上search过“所有演员”,而是倾向于search特定types的“A”,对“(A)”的search通常与像“static_cast <A>”。 使用更新的types,比如typesvalidation等,并不是因为它们使得search永远不会变得简单。