44

にキャストA*したいchar*場合とその逆の場合、2 つの選択肢があります (つまり、私たちの多くは 2 つの選択肢があると考えています。どちらも機能しているように見えるためです!したがって、混乱が生じます!):

struct A
{
    int age;
    char name[128];
};

A a;
char *buffer = static_cast<char*>(static_cast<void*>(&a)); //choice 1
char *buffer = reinterpret_cast<char*>(&a); //choice 2

どちらも正常に動作します。

//convert back
A *pA = static_cast<A*>(static_cast<void*>(buffer)); //choice 1
A *pA = reinterpret_cast<A*>(buffer); //choice 2

これでもうまくいきます!

では、連鎖した 2 つのジョブが機能するのに、なぜreinterpret_castC++ にあるのでしょうか。 static_cast

このトピックは、この投稿の下部にリストされているような以前のトピックと重複していると考える人もいるかもしれませんが、そうではありません。これらのトピックは理論的にしか議論していませんが、 が本当に必要な理由を示す例を 1 つも示してませ。1 つの static_cast が失敗することに同意します。しかし、2つではどうですか?reintepret_cast static_cast

2 つのチェーンの構文static_castが面倒に見える場合は、関数テンプレートを記述して、プログラマーにとってより使いやすくすることができます。

template<class To, class From>
To any_cast(From v)
{
    return static_cast<To>(static_cast<void*>(v));
}

そして、これを次のように使用できます。

char *buffer = any_cast<char*>(&a); //choice 1
char *buffer = reinterpret_cast<char*>(&a); //choice 2

//convert back
A *pA = any_cast<A*>(buffer); //choice 1
A *pA = reinterpret_cast<A*>(buffer); //choice 2

any_castまた、役立つ可能性があるこの状況を参照してください: fstream 読み取りおよび書き込みメンバー関数の適切なキャスト

だから私の質問は基本的に、

  • なぜreinterpret_castC++にあるのですか?
  • 連鎖した2つ static_castが同じ仕事を確実に失敗する例を1つでも教えてください。

4

7 に答える 7

36

reinterpret_cast一連のs ではできないことstatic_castができることがあります (すべて C++03 5.2.10 から):

  • ポインターは、それを保持するのに十分な大きさの任意の整数型に明示的に変換できます。

  • 整数型または列挙型の値は、明示的にポインターに変換できます。

  • 関数へのポインターは、異なる型の関数へのポインターに明示的に変換できます。

  • X「型のメンバーへのポインター」型の右辺値は、とが両方とも関数型または両方のオブジェクト型である場合、「型のT1メンバーへのポインター」型の右辺値に明示的に変換できます。YT2T1T2

また、C++03 9.2/17 から:

  • を使用して適切に変換された POD 構造体オブジェクトへのポインターは、reinterpret_castその最初のメンバー (または、そのメンバーがビットフィールドの場合は、それが存在するユニット) を指し、その逆も同様です。
于 2011-02-17T06:52:20.087 に答える
6

彼らができることに違いがある場合に他の人が与えた実際的な理由を除けば、それは別の仕事をしているので、持っているのは良いことです.

static_cast は、型 X のデータを Y に変換してくださいと言っています。 reinterpret_cast は、X のデータを Y として解釈してくださいと言っています。

基礎となる操作は同じであり、多くの場合、どちらでも機能する可能性があります。しかし、X を Y に変換してくださいということと、「はい、このデータが X として宣言されていることは知っていますが、実際には Y であるかのように使用してください」ということには概念的な違いがあります。

于 2011-02-17T08:29:35.990 に答える
6

具体例:

char a[4] = "Hi\n";
char* p = &a;

f(reinterpret_cast<char (&)[4]>(p));  // call f after restoring full type
      // ^-- any_cast<> can't do this...

// e.g. given...
template <typename T, int N>   // <=--- can match this function
void f(T (&)[N]) { std::cout << "array size " << N << '\n'; }
于 2011-02-17T07:33:24.640 に答える
3

私があなたの選択1(2つのチェーンされたstatic_cast)を伝えることができる限り、恐ろしい未定義の動作です。静的キャストは、ポインターを void * にキャストしてから元のポインターに戻すことのみを保証し、これらから変換された結果のポインターが元のオブジェクトを指すようにします。他のすべての変換は UB です。オブジェクト (ユーザー定義クラスのインスタンス) へのポインターの場合、static_cast はポインター値を変更する場合があります。

reinterpret_cast の場合 - ポインターの型を変更するだけで、私の知る限り - ポインターの値には決して触れません。

したがって、技術的に言えば、2 つの選択肢は同等ではありません。

編集:参照用に、static_cast は現在の C++0x ドラフトのセクション 5.2.9 で説明されています (申し訳ありませんが、C++03 標準はありません。現在と考えられるドラフトは n3225.pdf です)。許可されているすべての変換が記述されており、具体的にリストされていないものはすべて UB だと思います。したがって、そうすることを選択した場合、PC を吹き飛ばすことができます。

于 2011-02-17T09:35:26.150 に答える
0

C スタイルのキャストを使用するのは安全ではありません。異なるタイプが混在できるかどうかは決してチェックしません。C++ キャストは、関連するオブジェクトごとに (使用するキャストに基づいて) 型キャストが確実に行われるようにするのに役立ちます。これは、常に有害な従来の C スタイル キャストを使用するよりも推奨されるキャストの使用方法です。

于 2014-10-11T06:59:31.757 に答える
-1

皆さん、reinterpret_cast、static_cast、または他の 2 つの C++ スタイル キャスト (dynamic* と const) でさえ、実際には必要ありません。

C スタイルのキャストを使用する方が短く、4 つの C++ スタイルのキャストでできるすべてのことを実行できます。

anyType someVar = (anyOtherType)otherVar;

では、なぜ C++ スタイルのキャストを使用するのでしょうか。読みやすさ。第二に、より制限的なキャストにより、コードの安全性が向上するためです。

*わかりました、動的が必要な場合があります

于 2011-02-17T07:04:40.197 に答える