为什么使用 static_cast(x) 而不是 (T)x?
我听说 static_cast
函数应该优先于 C 风格或简单函数风格的转换。 这是真的? 为什么?
I've heard that the static_cast
function should be preferred to C-style or simple function-style casting. Is this true? Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
这与您想要施加多少类型安全有关。
当您编写
(bar) foo
(如果您没有提供类型转换运算符,则相当于reinterpret_castfoo
),您是在告诉编译器忽略类型安全,按规定行事。当你写
static_cast; foo
您要求编译器至少检查类型转换是否有意义,并且对于整型类型,插入一些转换代码。编辑2014-02-26
我在5年多前写了这个答案,但我错了。 (见评论。)但它仍然得到了支持!
It's about how much type-safety you want to impose.
When you write
(bar) foo
(which is equivalent toreinterpret_cast<bar> foo
if you haven't provided a type conversion operator) you are telling the compiler to ignore type safety, and just do as it's told.When you write
static_cast<bar> foo
you are asking the compiler to at least check that the type conversion makes sense and, for integral types, to insert some conversion code.EDIT 2014-02-26
I wrote this answer more than 5 years ago, and I got it wrong. (See comments.) But it still gets upvotes!
C 风格的强制转换很容易在代码块中被忽略。 C++ 风格的强制转换不仅是更好的实践,而且是更好的实践。 它们提供了更大程度的灵活性。
reinterpret_cast 允许整型到指针类型的转换,但如果误用可能会不安全。
static_cast 为数字类型提供了良好的转换,例如从枚举到整数或从整数到浮点数或您确信类型的任何数据类型。 它不执行任何运行时检查。
另一方面,dynamic_cast 将执行这些检查,标记任何不明确的赋值或转换。 它仅适用于指针和引用,并会产生开销。
还有其他一些,但这些是您会遇到的主要的。
C Style casts are easy to miss in a block of code. C++ style casts are not only better practice; they offer a much greater degree of flexibility.
reinterpret_cast allows integral to pointer type conversions, however can be unsafe if misused.
static_cast offers good conversion for numeric types e.g. from as enums to ints or ints to floats or any data types you are confident of type. It does not perform any run time checks.
dynamic_cast on the other hand will perform these checks flagging any ambiguous assignments or conversions. It only works on pointers and references and incurs an overhead.
There are a couple of others but these are the main ones you will come across.
static_cast
意味着您不会意外使用const_cast
或reinterpret_cast
,这是一件好事。static_cast
means that you can't accidentallyconst_cast
orreinterpret_cast
, which is a good thing.使用 grep 或类似的代码
工具。
你正在做的演员阵容,并且很吸引人
编译器帮助执行它。
如果你只想抛弃
const-ness,那么你可以使用
const_cast,这不允许你
进行其他类型的转换。
程序员正在推翻如何
编译器通常会处理你的
代码。 你是在对
编译器,“我比你更了解。”
既然如此,那就有道理了
表演演员应该是
做适度痛苦的事情,并且
他们应该在你的
代码,因为它们是可能的来源
的问题。
请参阅高效 C++ 简介
your code using grep or similar
tools.
of cast you are doing, and engaging
the compiler's help in enforcing it.
If you only want to cast away
const-ness, then you can use
const_cast, which will not allow you
to do other types of conversions.
a programmer are overruling how the
compiler would ordinarily treat your
code. You are saying to the
compiler, "I know better than you."
That being the case, it makes sense
that performing a cast should be a
moderately painful thing to do, and
that they should stick out in your
code, since they are a likely source
of problems.
See Effective C++ Introduction
问题不仅仅是使用
static_cast<>
还是 C 风格转换,因为使用 C 风格转换时会发生不同的情况。 C++ 转换运算符旨在使这些不同的操作更加明确。从表面上看,
static_cast<>
和 C 风格的转换似乎是同一件事,例如将一个值转换为另一个值时:这两种转换都将整数值转换为双精度值。 然而,当使用指针时,事情会变得更加复杂。 一些示例:
在此示例中,(1) 可能没问题,因为 A 指向的对象实际上是 B 的实例。但是,如果此时您不知道代码中
a
实际指向什么,该怎么办到?(2) 可能是完全合法的(您只想查看整数的一个字节),但它也可能是一个错误,在这种情况下,出现错误就好了,就像 (3) 一样。
C++ 转换运算符旨在通过在可能的情况下提供编译时或运行时错误来暴露代码中的这些问题。
因此,对于严格的“值转换”,您可以使用
static_cast<>
。 如果您想要指针的运行时多态转换,请使用dynamic_cast<>
。 如果您确实想忘记类型,可以使用reintrepret_cast
。 为了将const
扔出窗口,有const_cast<>
。他们只是让代码更加明确,让你看起来知道自己在做什么。
The question is bigger than just using whether
static_cast<>
or C-style casting because there are different things that happen when using C-style casts. The C++ casting operators are intended to make those different operations more explicit.On the surface
static_cast<>
and C-style casts appear to be the same thing, for example when casting one value to another:Both of those cast the integer value to a double. However when working with pointers things get more complicated. Some examples:
In this example (1) may be OK because the object pointed to by A is really an instance of B. But what if you don't know at that point in code what
a
actually points to?(2) may be perfectly legal (you only want to look at one byte of the integer), but it could also be a mistake in which case an error would be nice, like (3).
The C++ casting operators are intended to expose these issues in the code by providing compile-time or run-time errors when possible.
So, for strict "value casting" you can use
static_cast<>
. If you want run-time polymorphic casting of pointers usedynamic_cast<>
. If you really want to forget about types, you can usereintrepret_cast<>
. And to just throwconst
out the window there isconst_cast<>
.They just make the code more explicit so that it looks like you know what you were doing.
一个实用的提示:如果您打算整理项目,您可以轻松地在源代码中搜索
static_cast
关键字。One pragmatic tip: you can search easily for the
static_cast
keyword in your source code if you plan to tidy up the project.了解更多:
static_cast<> 和 static_cast 有什么区别 和 C 风格铸造
和
常规演员与 static_cast 与动态_cast
Read more on:
What is the difference between static_cast<> and C style casting
and
Regular cast vs. static_cast vs. dynamic_cast
static_cast 除了操作类指针之外,还可以用于执行类中显式定义的转换,以及执行基本类型之间的标准转换:
static_cast, aside from manipulating pointers to classes, can also be used to perform conversions explicitly defined in classes, as well as to perform standard conversions between fundamental types:
主要原因是经典的 C 转换对我们所说的
static_cast<>()
、reinterpret_cast<>()
、const_cast<> 和 static_cast<>() 之间没有区别。 ()
和dynamic_cast<>()
。 这四件事是完全不同的。static_cast<>()
通常是安全的。 语言中有一个有效的转换,或者有一个适当的构造函数使之成为可能。 唯一有点冒险的时候是当你向下转换为继承类时; 您必须通过语言外部的方式(如对象中的标志)确保该对象实际上是您声称的后代。 只要检查结果(指针)或考虑可能的异常(引用),dynamic_cast<>()
就是安全的。另一方面,reinterpret_cast<>()(或 const_cast<>())始终是危险的。 你告诉编译器:“相信我:我知道这看起来不像
foo
(这看起来好像它不可变),但它确实是”。第一个问题是,如果不查看大量分散的代码并了解所有规则,几乎不可能判断 C 风格类型转换中会出现哪一个。
让我们假设这些:
现在,这两个以相同的方式编译:
但是,让我们看看这个几乎相同的代码:
正如您所看到的,如果不了解所有涉及的类,就没有简单的方法来区分这两种情况。
第二个问题是 C 风格的强制转换太难定位。 在复杂的表达式中,很难看到 C 风格的强制转换。 如果没有成熟的 C++ 编译器前端,几乎不可能编写需要定位 C 风格转换的自动化工具(例如搜索工具)。 另一方面,很容易搜索“static_cast<” 或“reinterpret_cast<”。
这意味着,不仅 C 风格的强制转换更加危险,而且找到它们以确保它们正确也更加困难。
The main reason is that classic C casts make no distinction between what we call
static_cast<>()
,reinterpret_cast<>()
,const_cast<>()
, anddynamic_cast<>()
. These four things are completely different.A
static_cast<>()
is usually safe. There is a valid conversion in the language, or an appropriate constructor that makes it possible. The only time it's a bit risky is when you cast down to an inherited class; you must make sure that the object is actually the descendant that you claim it is, by means external to the language (like a flag in the object). Adynamic_cast<>()
is safe as long as the result is checked (pointer) or a possible exception is taken into account (reference).A
reinterpret_cast<>()
(or aconst_cast<>()
) on the other hand is always dangerous. You tell the compiler: "trust me: I know this doesn't look like afoo
(this looks as if it isn't mutable), but it is".The first problem is that it's almost impossible to tell which one will occur in a C-style cast without looking at large and disperse pieces of code and knowing all the rules.
Let's assume these:
Now, these two are compiled the same way:
However, let's see this almost identical code:
As you can see, there is no easy way to distinguish between the two situations without knowing a lot about all the classes involved.
The second problem is that the C-style casts are too hard to locate. In complex expressions it can be very hard to see C-style casts. It is virtually impossible to write an automated tool that needs to locate C-style casts (for example a search tool) without a full blown C++ compiler front-end. On the other hand, it's easy to search for "static_cast<" or "reinterpret_cast<".
That means that, not only are C-style casts more dangerous, but it's a lot harder to find them all to make sure that they are correct.