C++ 风格转换对性能的影响?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/674982/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:40:04  来源:igfitidea点击:

Performance hit from C++ style casts?

c++performancecasting

提问by Trevor Boyd Smith

I am new to C++ style casts and I am worried that using C++ style casts will ruin the performance of my applicationbecause I have a real-time-critical deadlinein my interrupt-service-routine.

我是 C++ 样式转换的新手,我担心使用 C++ 样式转换会破坏我的应用程序的性能,因为我的中断服务例程中有一个实时关键的截止日期

I heard that some casts will even throw exceptions!

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

I would like to use the C++ style casts because it would make my code more "robust". However, if there is any performance hitthen I will probably not use C++ style casts and will instead spend more time testing the code that uses C-style casts.

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



Has anyone done any rigorous testing/profiling to compare the performance of C++ style casts to C style casts?

有没有人做过任何严格的测试/分析来比较 C++ 风格强制转换和 C 风格强制转换的性能?

What were your results?

你的结果如何?

What conclusions did you draw?

你得出了什么结论?

回答by

If the C++ style cast can be conceptualy replaced by a C-style cast there will be no overhead. If it can't, as in the case of dynamic_cast, for which there is no C equivalent, you have to pay the cost one way or another.

如果 C++ 样式转换可以在概念上被 C 样式转换替换,则不会有任何开销。如果它不能,例如dynamic_cast没有 C 等价物的 ,则您必须以某种方式支付成本。

As an example, the following code:

例如,以下代码:

int x;
float f = 123.456;

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

generates identical code for both casts with VC++ - code is:

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

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

The only C++ cast that can throw is dynamic_castwhen casting to a reference. To avoid this, cast to a pointer, which will return 0 if the cast fails.

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

回答by Daniel Earwicker

The only one with any extra cost at runtime is dynamic_cast, which has capabilities that cannot be reproduced directly with a C style cast anyway. So you have no problem.

唯一一个在运行时会产生额外成本的是dynamic_cast,它具有无论如何都无法直接用 C 样式转换来复制的功能。所以你没有问题。

The easiest way to reassure yourself of this is to instruct your compiler to generate assembler output, and examine the code it generates. For example, in any sanely implemented compiler, reinterpret_castwill disappear altogether, because it just means "go blindly ahead and pretend the data is of this type".

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

回答by jalf

Why would there be a performance hit? They perform exactlythe same functionality as C casts. The only difference is that they catch more errors at compile-time, and they're easier to search for in your source code.

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

static_cast<float>(3)is exactly equivalent to (float)3, and will generate exactly the same code.

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

Given a float f = 42.0freinterpret_cast<int*>(&f)is exactly equivalent to (int*)&f, and will generate exactly the same code.

给定 afloat f = 42.0freinterpret_cast<int*>(&f)完全等同于(int*)&f,并且将生成完全相同的代码。

And so on. The only cast that differs is dynamic_cast, which, yes, can throw an exception. But that is because it does things that the C-style cast cannot do. So don't use dynamic_castunless you need its functionality.

等等。唯一不同的类型是dynamic_cast,是的,它可以抛出异常。但那是因为它可以完成 C 风格类型转换无法完成的事情。所以dynamic_cast除非你需要它的功能,否则不要使用。

It is usually safe to assume that compiler writers are intelligent. Given two different expressions that have the same semantics according to the standard, it is usually safe to assume that they will be implemented identically in the compiler.

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

Oops: The second example should be reinterpret_cast, not dynamic_cast, of course. Fixed it now.

哎呀:当然,第二个例子应该是 reinterpret_cast,而不是 dynamic_cast。现在修好了。

Ok, just to make it absolutely clear, here is what the C++ standard says:

好的,只是为了让它绝对清楚,这是 C++ 标准所说的:

§5.4.5:

§5.4.5:

The conversions performed by

  • a const_cast(5.2.11)
  • a static_cast(5.2.9)
  • a static_castfollowed by a const_cast
  • a reinterpret_cast(5.2.10), or
  • a reinterpret_castfollowed by a const_cast.

can be performed using the cast notation of explicit type conversion. The same semantic restrictions and behaviors apply. If a conversion can be interpreted in more than one of the ways listed above, the interpretation that appears first in the list is used, even if a cast resulting from that interpretation is ill-formed.

执行的转换

  • 一个const_cast(5.2.11)
  • 一个static_cast(5.2.9)
  • 一个static_cast接着一个const_cast
  • a reinterpret_cast(5.2.10),或
  • areinterpret_cast后跟 a const_cast

可以使用显式类型转换的强制转换表示法来执行。相同的语义限制和行为适用。如果可以用以上列出的多种方式解释转换,则使用列表中第一个出现的解释,即使由该解释产生的强制转换格式不正确。

So if anything, since the C-style cast is implemented in terms of the C++ casts, C-style casts should be slower. (of course they aren't, because the compiler generates the same code in any case, but it's more plausible than the C++-style casts being slower.)

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

回答by Max Lybbert

There are four C++ style casts:

有四种 C++ 风格的类型转换:

  • const_cast
  • static_cast
  • reinterpret_cast
  • dynamic_cast
  • const_cast
  • static_cast
  • reinterpret_cast
  • dynamic_cast

As already mentioned, the first three are compile-time operations. There is no run-time penalty for using them. They are messages to the compiler that data that has been declared one way needs to be accessed a different way. "I said this was an int*, but let me access it as if it were a char*pointing to sizeof(int) chars" or "I said this data was read-only, and now I need to pass it to a function that won't modify it, but doesn't take the parameter as a const reference."

如前所述,前三个是编译时操作。使用它们没有运行时惩罚。它们是给编译器的消息,表明以一种方式声明的数据需要以不同的方式访问。“我说,这是一个int*,但让我访问它,仿佛它是一个char*指向sizeof(int) chars”或“我说这个数据是只读的,现在我需要把它传递给不会改变它的功能,但不将该参数作为常量引用。”

Aside from data corruption by casting to the wrong type and trouncing over data (always a possibility with C-style casts) the most common run-time problem with these casts is data that actually is declared constmay not be castable to non-const. Casting something declared constto non-const and then modifying it is undefined. Undefined means you're not even guaranteed to get a crash.

除了通过强制转换为错误类型和破坏数据而导致的数据损坏(C 风格强制转换总是可能的)之外,这些强制转换最常见的运行时问题是实际声明的数据const可能无法转换为非常量。将一些声明const为非常量的东西然后修改它是未定义的。 未定义意味着您甚至不能保证会崩溃

dynamic_castis a run-time construct and has to have a run-time cost.

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

The value of these casts is that they specifically say what you're trying to cast from/to, stick out visually, and can be searched for with brain-dead tools. I would recommend using them over using C-style casts.

这些演员表的价值在于,它们特别说明了您要从/向哪个演员表投射的内容,在视觉上突出显示,并且可以使用脑死工具进行搜索。我建议使用它们而不是使用 C 风格的强制转换。

回答by tstenner

When using dynamic_castseveral checks are made during runtime to prevent you from doing something stupid (more at the GCC mailing list), the cost of one dynamic_castdepends on how many classes are affected, what classes are affected, etc.
If you're really sure the cast is safe, you can still use reinterpret_cast.

dynamic_cast在运行时使用多个检查来防止你做一些愚蠢的事情时(更多在GCC 邮件列表中),一个的成本dynamic_cast取决于有多少类受到影响,哪些类受到影响等。
如果你真的确定cast 是安全的,您仍然可以使用reinterpret_cast.

回答by leander

Although I agree with the statement "the only one with any extra cost at runtime is dynamic_cast", keep in mind there may be compiler-specific differences.

尽管我同意“唯一在运行时产生额外成本的情况”这一说法dynamic_cast,但请记住,可能存在特定于编译器的差异。

I've seen a few bugs filed against my current compiler where the code generation or optimization was slightly different depending on whether you use a C-style vs. C++-style static_castcast.

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

So if you're worried, check the disassembly on hotspots. Otherwise just avoid dynamic casts when you don't need them. (If you turn off RTTI, you can't use dynamic_castanyway.)

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

回答by user3726672

The canonical truth is the assembly, so try both and see if you get different logic.

规范的事实是程序集,所以尝试两者,看看你是否得到不同的逻辑。

If you get the exact same assembly, there is no difference- there can't be. The only place you really need to stick with the old C casts is in pure C routines and libraries, where it makes no sense to introduce C++ dependence just for type casting.

如果您获得完全相同的组件,则没有区别 - 不可能。您真正需要坚持使用旧的 C 强制转换的唯一地方是在纯 C 例程和库中,在那里引入 C++ 依赖仅用于类型转换是没有意义的。

One thing to be aware of is that casts happen all over the place in a decent sized piece of code. In my entire career I've never searched on "all casts" in a piece of logic- you tend to search for casts to a specific TYPE like 'A', and a search on "(A)" is usually just as efficient as something like "static_cast<A>". Use the newer casts for things like type validation and such, not because they make searches you'll never do anyway easier.

需要注意的一件事是,在一段适当大小的代码中,强制转换发生在各个地方。在我的整个职业生涯中,我从未在逻辑中搜索过“所有类型转换”——你倾向于搜索像“A”这样的特定类型的类型转换,而搜索“(A)”的效率通常与类似于“static_cast<A>”。将较新的强制转换用于诸如类型验证之类的事情,而不是因为它们使您永远不会更轻松地进行搜索。