C++ 为什么使用 static_cast<int>(x) 而不是 (int)x?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/103512/
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
Why use static_cast<int>(x) instead of (int)x?
提问by Tommy Herbert
I've heard that the static_cast
function should be preferred to C-style or simple function-style casting. Is this true? Why?
我听说static_cast
函数应该优先于 C 风格或简单的函数风格转换。这是真的?为什么?
采纳答案by Euro Micelli
The main reason is that classic C casts make no distinction between what we call static_cast<>()
, reinterpret_cast<>()
, const_cast<>()
, and dynamic_cast<>()
. These four things are completely different.
主要的原因是,经典的C类型转换让我们所说的没有区别static_cast<>()
,reinterpret_cast<>()
,const_cast<>()
,和dynamic_cast<>()
。这四件事是完全不同的。
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). A dynamic_cast<>()
is safe as long as the result is checked (pointer) or a possible exception is taken into account (reference).
Astatic_cast<>()
通常是安全的。语言中有一个有效的转换,或者一个合适的构造函数使之成为可能。唯一有点冒险的时候是当你转换到一个继承的类时;您必须通过语言外部的方式(如对象中的标志)确保该对象实际上是您声称的后代。dynamic_cast<>()
只要检查结果(指针)或考虑可能的异常(引用),A就是安全的。
A reinterpret_cast<>()
(or a const_cast<>()
) on the other hand is always dangerous. You tell the compiler: "trust me: I know this doesn't look like a foo
(this looks as if it isn't mutable), but it is".
A reinterpret_cast<>()
(或 a const_cast<>()
) 另一方面总是危险的。你告诉编译器:“相信我:我知道这看起来不像 a foo
(这看起来好像不可变),但它是”。
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.
第一个问题是,如果不查看大量分散的代码并了解所有规则,几乎不可能判断哪个会出现在 C 风格的强制转换中。
Let's assume these:
让我们假设这些:
class CDerivedClass : public CMyBase {...};
class CMyOtherStuff {...} ;
CMyBase *pSomething; // filled somewhere
Now, these two are compiled the same way:
现在,这两个以相同的方式编译:
CDerivedClass *pMyObject;
pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked
pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<>
// Safe; as long as we checked
// but harder to read
However, let's see this almost identical code:
但是,让我们看看这段几乎相同的代码:
CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert
pOther = (CMyOtherStuff*)(pSomething); // No compiler error.
// Same as reinterpret_cast<>
// and it's wrong!!!
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<".
第二个问题是 C 风格的类型转换太难定位了。在复杂的表达式中,很难看到 C 风格的强制转换。如果没有完整的 C++ 编译器前端,几乎不可能编写需要定位 C 样式转换(例如搜索工具)的自动化工具。另一方面,很容易搜索“static_cast<”或“reinterpret_cast<”。
pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
// No compiler error.
// but the presence of a reinterpret_cast<> is
// like a Siren with Red Flashing Lights in your code.
// The mere typing of it should cause you to feel VERY uncomfortable.
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.
这意味着,不仅 C 风格的强制转换更危险,而且要找到所有这些以确保它们是正确的要困难得多。
回答by Karl
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 关键字。
回答by Rika
In short:
static_cast<>()
gives you a compile time checking ability, C-Style cast doesn't.static_cast<>()
can be spotted easily anywhere inside a C++ source code; in contrast, C_Style cast is harder to spot.- Intentions are conveyed much better using C++ casts.
More Explanation:
The static cast performs conversions between compatible types. It is similar to the C-style cast, but is more restrictive. For example, the C-style cast would allow an integer pointer to point to a char.
char c = 10; // 1 byte int *p = (int*)&c; // 4 bytes
Since this results in a 4-byte pointer pointing to 1 byte of allocated memory, writing to this pointer will either cause a run-time error or will overwrite some adjacent memory.
*p = 5; // run-time error: stack corruption
In contrast to the C-style cast, the static cast will allow the compiler to check that the pointer and pointee data types are compatible, which allows the programmer to catch this incorrect pointer assignment during compilation.
int *q = static_cast<int*>(&c); // compile-time error
简而言之:
static_cast<>()
给你一个编译时检查能力,C-Style cast 没有。static_cast<>()
可以很容易地在 C++ 源代码中的任何地方发现;相比之下,C_Style 类型转换更难发现。- 使用 C++ 强制转换可以更好地传达意图。
更多解释:
静态类型转换执行兼容类型之间的转换。它类似于 C 风格的强制转换,但限制性更强。例如,C 风格的强制转换将允许一个整数指针指向一个字符。
char c = 10; // 1 byte int *p = (int*)&c; // 4 bytes
由于这会导致 4 字节的指针指向 1 字节的已分配内存,因此写入此指针将导致运行时错误或覆盖某些相邻内存。
*p = 5; // run-time error: stack corruption
与 C 风格的转换不同,静态转换将允许编译器检查指针和被指点数据类型是否兼容,这允许程序员在编译期间捕获这种不正确的指针分配。
int *q = static_cast<int*>(&c); // compile-time error
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<> 和 C 风格的强制类型转换
和常规类型转换、static_cast 和 dynamic_cast之间的区别是什么
回答by Dusty Campbell
The question is bigger than just using wither 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 these operations more explicit.
问题不仅仅是使用 wither static_cast 或 C 样式转换,因为在使用 C 样式转换时会发生不同的事情。C++ 转换运算符旨在使这些操作更加明确。
On the surface static_cast and C style casts appear to the same thing, for example when casting one value to another:
从表面上看,static_cast 和 C 风格的转换看起来是一样的,例如当将一个值转换为另一个值时:
int i;
double d = (double)i; //C-style cast
double d2 = static_cast<double>( i ); //C++ cast
Both of these cast the integer value to a double. However when working with pointers things get more complicated. some examples:
这两个都将整数值转换为双精度值。然而,当使用指针时,事情变得更加复杂。一些例子:
class A {};
class B : public A {};
A* a = new B;
B* b = (B*)a; //(1) what is this supposed to do?
char* c = (char*)new int( 5 ); //(2) that weird?
char* c1 = static_cast<char*>( new int( 5 ) ); //(3) compile time error
In this example (1) maybe 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) maybe 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.
在这个例子中 (1) 可能没问题,因为 A 指向的对象实际上是 B 的一个实例。但是如果你在代码中不知道 a 实际指向的那个点怎么办?(2) 可能完全合法(您只想查看整数的一个字节),但也可能是一个错误,在这种情况下,错误会很好,例如(3)。C++ 转换运算符旨在通过在可能的情况下提供编译时或运行时错误来暴露代码中的这些问题。
So, for strict "value casting" you can use static_cast. If you want run-time polymorphic casting of pointers use dynamic_cast. If you really want to forget about types, you can use reintrepret_cast. And to just throw const out the window there is const_cast.
因此,对于严格的“值转换”,您可以使用 static_cast。如果您想要指针的运行时多态转换,请使用 dynamic_cast。如果你真的想忘记类型,你可以使用 reintrepret_cast。并且只是将 const 抛出窗口有 const_cast。
They just make the code more explicit so that it looks like you know what you were doing.
他们只是让代码更明确,这样看起来你就知道自己在做什么。
回答by DrPizza
static_cast
means that you can't accidentally const_cast
or reinterpret_cast
, which is a good thing.
static_cast
意味着您不能意外const_cast
或reinterpret_cast
,这是一件好事。
回答by Pitarou
It's about how much type-safety you want to impose.
这是关于你想要强加多少类型安全。
When you write (bar) foo
(which is equivalent to reinterpret_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.
当您编写时(bar) foo
(相当于reinterpret_cast<bar> foo
您没有提供类型转换运算符),您是在告诉编译器忽略类型安全,并按照它的指示去做。
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.
当您编写时,static_cast<bar> foo
您要求编译器至少检查类型转换是否有意义,并且对于整数类型,插入一些转换代码。
EDIT 2014-02-26
编辑 2014-02-26
I wrote this answer more than 5 years ago, and I got it wrong. (See comments.) But it still gets upvotes!
我在 5 年前写了这个答案,但我弄错了。(见评论。)但它仍然得到赞成!
回答by JohnMcG
- Allows casts to be found easily in your code using grep or similar tools.
- Makes it explicit what kind 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.
- Casts are inherently ugly -- you as 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.
- 允许使用 grep 或类似工具在您的代码中轻松找到强制转换。
- 明确你在做什么类型的转换,并让编译器帮助执行它。如果你只想抛弃 const-ness,那么你可以使用 const_cast,它不允许你做其他类型的转换。
- 强制转换本质上是丑陋的——作为程序员的您正在否决编译器通常如何处理您的代码。你对编译器说:“我比你更了解。” 在这种情况下,执行强制转换应该是一件相当痛苦的事情,并且它们应该在您的代码中突出显示,因为它们可能是问题的根源。
See Effective C++Introduction
请参阅有效的 C++介绍
回答by Konrad
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.
C 样式转换很容易在代码块中遗漏。C++ 风格的强制转换不仅是更好的实践;它们提供了更大程度的灵活性。
reinterpret_cast allows integral to pointer type conversions, however can be unsafe if misused.
reinterpret_cast 允许整数到指针类型转换,但是如果误用可能是不安全的。
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.
static_cast 为数字类型提供了良好的转换,例如从枚举到整数或整数到浮点数或您确信类型的任何数据类型。它不执行任何运行时检查。
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.
另一方面,dynamic_cast 将执行这些检查,标记任何不明确的分配或转换。它仅适用于指针和引用并会产生开销。
There are a couple of others but these are the main ones you will come across.
还有其他几个,但这些是您会遇到的主要问题。
回答by prakash
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:
static_cast 除了操作指向类的指针外,还可用于执行类中显式定义的转换,以及执行基本类型之间的标准转换:
double d = 3.14159265;
int i = static_cast<int>(d);