为什么使用static_cast(x)而不是(int)x?

时间:2023-01-26 11:48:01

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样式或简单的函数样式。这是真的吗?为什么?

9 个解决方案

#1


519  

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 a 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).

static_cast<>()通常是安全的。语言中有一个有效的转换,或者有一个合适的构造函数使它成为可能。唯一有一点风险的时候是当你把它丢给一个继承的类;您必须确保对象实际上是您所声称的后代,通过外部语言(例如对象中的标志)。只要检查结果(指针)或考虑可能的异常(引用),dynamic_cast<>()是安全的。

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".

另一方面,reinterpret_cast<>()(或const_cast<>()))总是很危险的。你告诉编译器:“相信我:我知道这看起来不像一个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 CMyClass : public CMyBase {...};
class CMyOtherStuff {...} ;

CMyBase  *pSomething; // filled somewhere

Now, these two are compiled the same way:

这两种方法是一样的:

CMyClass *pMyObject;
pMyObject = static_cast<CMyClass*>(pSomething); // Safe; as long as we checked

pMyObject = (CMyClass*)(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<”或“reviewt_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型铸造更危险,而且要找到它们来确保它们是正确的也要困难得多。

#2


101  

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关键字。

#3


51  

In short:

简而言之:

  1. static_cast<>() gives you a compile time checking ability, C-Style cast doesn't.
  2. static_cast<>()为您提供了一个编译时检查能力,c风格的cast没有。
  3. static_cast<>() can be spotted easily anywhere inside a C++ source code; in contrast, C_Style cast is harder to spot.
  4. static_cast<>()可以很容易地在c++源代码中的任何位置找到;相比之下,C_Style cast更难以识别。
  5. Intentions are conveyed much better using C++ casts.
  6. 使用c++强制类型转换可以更好地表达意图。

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.

静态强制转换在兼容类型之间执行转换。它类似于c型铸造,但有更多的限制。例如,c样式转换允许一个指向字符的整数指针。

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.

由于这会导致一个4字节的指针指向一个字节的已分配内存,因此写入这个指针将导致运行时错误,或者覆盖一些相邻的内存。

*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.

与c风格的转换不同,静态转换将允许编译器检查指针和pointee数据类型是否兼容,这允许程序员在编译过程中捕获错误的指针分配。

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风格的转换与常规的cast与static_cast和dynamic_cast的区别是什么?

#4


26  

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 style cast要大,因为在使用C style cast时,会发生不同的事情。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 style cast看起来是一样的,例如当将一个值转换为另一个值时:

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:

这两种方法都将整数值转换为double。然而,当使用指针时,事情就变得更加复杂了。一些例子:

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的一个实例,但是如果你在代码中不知道实际指向的是什么呢?(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.

他们只是让代码更明确,这样看起来你知道你在做什么。

#5


21  

static_cast means that you can't accidentally const_cast or reinterpret_cast, which is a good thing.

static_cast意味着您不能意外地const_cast或reviewt_cast,这是一件好事。

#6


7  

  1. Allows casts to be found easily in your code using grep or similar tools.
  2. 允许使用grep或类似工具在代码中轻松找到类型转换。
  3. 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.
  4. 明确您正在执行的类型强制转换,并让编译器提供帮助。如果您只想丢弃const,那么您可以使用const_cast,这将不允许您执行其他类型的转换。
  5. 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.
  6. 强制类型转换本质上是丑陋的——作为程序员,您正在否决编译器通常如何对待您的代码。你对编译器说:“我比你知道得多。”在这种情况下,执行一个角色应该是一个比较痛苦的事情,并且他们应该在你的代码中坚持,因为他们可能是问题的根源。

See Effective C++ Introduction

看到有效的c++的介绍

#7


7  

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(如果没有提供类型转换操作符,则相当于reinterpretation t_cast 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 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年前写的,我错了。(见注释)。但它仍然获得了更多的选票!

#8


4  

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为数字类型提供了很好的转换,例如从as enums转换为int类型,或者从int类型转换为float类型,或者您对类型有信心的任何数据类型。它不执行任何运行时检查。

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.

还有一些其他的,但是这些是你会遇到的主要的。

#9


3  

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);

#1


519  

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 a 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).

static_cast<>()通常是安全的。语言中有一个有效的转换,或者有一个合适的构造函数使它成为可能。唯一有一点风险的时候是当你把它丢给一个继承的类;您必须确保对象实际上是您所声称的后代,通过外部语言(例如对象中的标志)。只要检查结果(指针)或考虑可能的异常(引用),dynamic_cast<>()是安全的。

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".

另一方面,reinterpret_cast<>()(或const_cast<>()))总是很危险的。你告诉编译器:“相信我:我知道这看起来不像一个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 CMyClass : public CMyBase {...};
class CMyOtherStuff {...} ;

CMyBase  *pSomething; // filled somewhere

Now, these two are compiled the same way:

这两种方法是一样的:

CMyClass *pMyObject;
pMyObject = static_cast<CMyClass*>(pSomething); // Safe; as long as we checked

pMyObject = (CMyClass*)(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<”或“reviewt_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型铸造更危险,而且要找到它们来确保它们是正确的也要困难得多。

#2


101  

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关键字。

#3


51  

In short:

简而言之:

  1. static_cast<>() gives you a compile time checking ability, C-Style cast doesn't.
  2. static_cast<>()为您提供了一个编译时检查能力,c风格的cast没有。
  3. static_cast<>() can be spotted easily anywhere inside a C++ source code; in contrast, C_Style cast is harder to spot.
  4. static_cast<>()可以很容易地在c++源代码中的任何位置找到;相比之下,C_Style cast更难以识别。
  5. Intentions are conveyed much better using C++ casts.
  6. 使用c++强制类型转换可以更好地表达意图。

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.

静态强制转换在兼容类型之间执行转换。它类似于c型铸造,但有更多的限制。例如,c样式转换允许一个指向字符的整数指针。

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.

由于这会导致一个4字节的指针指向一个字节的已分配内存,因此写入这个指针将导致运行时错误,或者覆盖一些相邻的内存。

*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.

与c风格的转换不同,静态转换将允许编译器检查指针和pointee数据类型是否兼容,这允许程序员在编译过程中捕获错误的指针分配。

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风格的转换与常规的cast与static_cast和dynamic_cast的区别是什么?

#4


26  

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 style cast要大,因为在使用C style cast时,会发生不同的事情。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 style cast看起来是一样的,例如当将一个值转换为另一个值时:

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:

这两种方法都将整数值转换为double。然而,当使用指针时,事情就变得更加复杂了。一些例子:

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的一个实例,但是如果你在代码中不知道实际指向的是什么呢?(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.

他们只是让代码更明确,这样看起来你知道你在做什么。

#5


21  

static_cast means that you can't accidentally const_cast or reinterpret_cast, which is a good thing.

static_cast意味着您不能意外地const_cast或reviewt_cast,这是一件好事。

#6


7  

  1. Allows casts to be found easily in your code using grep or similar tools.
  2. 允许使用grep或类似工具在代码中轻松找到类型转换。
  3. 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.
  4. 明确您正在执行的类型强制转换,并让编译器提供帮助。如果您只想丢弃const,那么您可以使用const_cast,这将不允许您执行其他类型的转换。
  5. 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.
  6. 强制类型转换本质上是丑陋的——作为程序员,您正在否决编译器通常如何对待您的代码。你对编译器说:“我比你知道得多。”在这种情况下,执行一个角色应该是一个比较痛苦的事情,并且他们应该在你的代码中坚持,因为他们可能是问题的根源。

See Effective C++ Introduction

看到有效的c++的介绍

#7


7  

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(如果没有提供类型转换操作符,则相当于reinterpretation t_cast 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 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年前写的,我错了。(见注释)。但它仍然获得了更多的选票!

#8


4  

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为数字类型提供了很好的转换,例如从as enums转换为int类型,或者从int类型转换为float类型,或者您对类型有信心的任何数据类型。它不执行任何运行时检查。

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.

还有一些其他的,但是这些是你会遇到的主要的。

#9


3  

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);