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

发布于 2024-07-04 18:58:49 字数 72 浏览 9 评论 0原文

我听说 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

半寸时光 2024-07-11 18:58:49

这与您想要施加多少类型安全有关。

当您编写 (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 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.

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!

孤独陪着我 2024-07-11 18:58:49

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.

爱,才寂寞 2024-07-11 18:58:49

static_cast 意味着您不会意外使用 const_castreinterpret_cast,这是一件好事。

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

虚拟世界 2024-07-11 18:58:49
  1. 允许在以下位置轻松找到演员表
    使用 grep 或类似的代码
    工具。
  2. 明确表明什么类型
    你正在做的演员阵容,并且很吸引人
    编译器帮助执行它。
    如果你只想抛弃
    const-ness,那么你可以使用
    const_cast,这不允许你
    进行其他类型的转换。
  3. 演员阵容本质上是丑陋的——你作为
    程序员正在推翻如何
    编译器通常会处理你的
    代码。 你是在对
    编译器,“我比你更了解。”
    既然如此,那就有道理了
    表演演员应该是
    做适度痛苦的事情,并且
    他们应该在你的
    代码,因为它们是可能的来源
    的问题。

请参阅高效 C++ 简介

  1. Allows casts to be found easily in
    your code using grep or similar
    tools.
  2. 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.
  3. 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.

See Effective C++ Introduction

本宫微胖 2024-07-11 18:58:49

问题不仅仅是使用 static_cast<> 还是 C 风格转换,因为使用 C 风格转换时会发生不同的情况。 C++ 转换运算符旨在使这些不同的操作更加明确。

从表面上看,static_cast<> 和 C 风格的转换似乎是同一件事,例如将一个值转换为另一个值时:

int i;
double d = (double)i;                  //C-style cast
double d2 = static_cast<double>( i );  //C++ cast

这两种转换都将整数值转换为双精度值。 然而,当使用指针时,事情会变得更加复杂。 一些示例:

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

在此示例中,(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:

int i;
double d = (double)i;                  //C-style cast
double d2 = static_cast<double>( i );  //C++ cast

Both of those 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) 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 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<>.

They just make the code more explicit so that it looks like you know what you were doing.

你又不是我 2024-07-11 18:58:49

一个实用的提示:如果您打算整理项目,您可以轻松地在源代码中搜索 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.

迷荒 2024-07-11 18:58:49

简而言之

  1. static_cast<>() 为您提供编译时检查能力,C 风格
    演员阵容没有。
  2. static_cast<>() 很容易被发现
    C++ 源代码中的任何位置; 相比之下,C_Style 类型转换更难发现。
  3. 使用 C++ 转换可以更好地传达意图。

更多说明

静态转换执行兼容类型之间的转换。 它
与 C 风格的演员阵容类似,但限制更多。 例如,
C 风格的转换将允许整数指针指向字符。

char c = 10;   // 1 字节 
  int *p = (int*)&c;   // 4字节 
  

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

<前><代码>*p = 5; // 运行时错误:堆栈损坏

与 C 风格的强制转换相比,静态强制转换将允许
编译器检查指针和指针数据类型是否为
兼容,这允许程序员捕获这个不正确的
编译期间的指针赋值。

int *q = static_cast(&c);   // 编译时错误 
  

了解更多:
static_cast<> 和 static_cast 有什么区别 和 C 风格铸造

常规演员与 static_cast 与动态_cast

In short:

  1. static_cast<>() gives you a compile time checking ability, C-Style
    cast doesn't.
  2. static_cast<>() can be spotted easily
    anywhere inside a C++ source code; in contrast, C_Style cast is harder to spot.
  3. 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

Read more on:
What is the difference between static_cast<> and C style casting
and
Regular cast vs. static_cast vs. dynamic_cast

几味少女 2024-07-11 18:58:49

static_cast 除了操作类指针之外,还可以用于执行类中显式定义的转换,以及执行基本类型之间的标准转换:

double d = 3.14159265;
int    i = static_cast<int>(d);

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:

double d = 3.14159265;
int    i = static_cast<int>(d);
苍景流年 2024-07-11 18:58:49

主要原因是经典的 C 转换对我们所说的 static_cast<>()reinterpret_cast<>()const_cast<> 和 static_cast<>() 之间没有区别。 ()dynamic_cast<>()。 这四件事是完全不同的。

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

另一方面,reinterpret_cast<>()(或 const_cast<>())始终是危险的。 你告诉编译器:“相信我:我知道这看起来不像 foo (这看起来好像它不可变),但它确实是”。

第一个问题是,如果不查看大量分散的代码并了解所有规则,几乎不可能判断 C 风格类型转换中会出现哪一个。

让我们假设这些:

class CDerivedClass : public CMyBase {...};
class CMyOtherStuff {...} ;

CMyBase  *pSomething; // filled somewhere

现在,这两个以相同的方式编译:

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

但是,让我们看看这个几乎相同的代码:

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!!!

正如您所看到的,如果不了解所有涉及的类,就没有简单的方法来区分这两种情况。

第二个问题是 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.

这意味着,不仅 C 风格的强制转换更加危险,而且找到它们以确保它们正确也更加困难。

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.

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

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

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:

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文