40 votes

Pourquoi avons-nous reinterpret_cast en C ++ alors que deux chaînes chaînées static_cast peuvent faire leur travail?

Dire que j'ai envie de jeter A* de char* , et vice-versa, nous avons deux choix (je veux dire, beaucoup d'entre nous pense que nous avons deux choix, car les deux ne fonctionne! D'où la confusion!):

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

Les deux fonctionnent très bien.

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

Même cela fonctionne très bien!

Alors, pourquoi ne nous ont reinterpret_cast en C++ quand deux enchaînés static_cast peut faire son travail?

Certains d'entre vous pense que ce sujet est un doublon de la précédente sujets tels que répertoriés au bas de ce post, mais il ne l'est pas. Ces sujets de discuter seulement en théorie, mais aucun d'entre eux donne un seul exemple qui démontre pourquoi reintepret_cast ce qui est vraiment nécessaire, et deux static_cast serait sûrement échouer. Je suis d'accord, un static_cast serait un échec. Mais comment environ deux?

Si la syntaxe de deux enchaînés static_cast semble lourd, alors on peut écrire une fonction de modèle pour le rendre plus programmeur de l'environnement:

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

Et puis on peut l'utiliser, comme:

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

Voir également cette situation, où l' any_cast peut être utile: Bon casting pour fstream de lire et d'écrire des fonctions de membre du.

Donc ma question est fondamentalement,

  • Pourquoi avons-nous reinterpret_cast en C++?
  • Montrez-moi un seul exemple où les deux enchaînés static_cast serait certainement pas de faire le même travail?

36voto

James McNellis Points 193607

Il y a des choses qu' reinterpret_cast peut faire qu'aucune séquence de static_casts peut faire (tous à partir de C++03 5.2.10):

  • Un pointeur peut être explicitement converti à n'importe quel type intégral suffisamment grande pour l'accueillir.

  • Une valeur de type intégral ou de type énumération peut être explicitement converti en pointeur.

  • Un pointeur vers une fonction peut être explicitement converti en un pointeur vers une fonction d'un type différent.

  • Une rvalue de type "pointeur de membre de l' X de type T1" peut être converties explicitement à une rvalue de type "pointeur de membre de l' Y de type T2" si T1 et T2 sont à la fois des types de fonction ou les deux types d'objet.

Aussi, à partir de C++03 9.2/17:

  • Un pointeur vers un POD-struct objet, convenablement converti à l'aide d'un reinterpret_cast, points à son premier membre (ou si le membre est un peu de champ, puis à l'unité dans laquelle il se trouve), et vice-versa.

15voto

sharptooth Points 93379

Vous avez besoin de reinterpret_cast pour obtenir un pointeur avec une adresse codée en dur (comme ici ):

 int* pointer = reinterpret_cast<int*>( 0x1234 );
 

vous voudrez peut-être avoir ce code pour accéder à un port d'entrée-sortie de périphérique mappé en mémoire.

6voto

Tony D Points 43962

Un exemple concret :

5voto

jcoder Points 14982

Autres que des raisons d'ordre pratique que d'autres ont donné où il y a une différence dans ce qu'ils peuvent faire c'est une bonne chose parce que sa fait un travail différent.

static_cast est dire s'il vous plaît convertir des données de type X à Y. reinterpret_cast est dire s'il vous plaît interpréter les données en X sous la forme d'un Y.

Il se pourrait bien que les opérations sous-jacentes sont les mêmes, et que l'un et l'autre travaillent dans de nombreux cas. Mais il existe une différence conceptuelle entre le dire s'il vous plaît convertir X en Y, et disant: "oui, je sais que ces données sont déclarées comme un X mais merci de l'utiliser comme si c'était vraiment un Y".

3voto

Tomek Points 2742

Aussi loin que je peux dire à votre choix 1 (deux enchaînés static_cast) est redouté comportement indéfini. Statique de la fonte ne garantit que la conversion de pointeur de type void*, puis retour à l'original pointeur travaille dans une manière que le pointeur résultant de ces conversions encore des points à l'objet d'origine. Toutes les autres conversions sont UB. Pour des pointeurs vers des objets (instances de classes définies par l'utilisateur) static_cast peut modifier la valeur du pointeur.

Pour le reinterpret_cast - il modifie uniquement le type du pointeur et autant que je sache, elle n'a jamais touche la valeur du pointeur.

Donc, techniquement parlant, les deux choix ne sont pas équivalentes.

EDIT: Pour la référence, static_cast est décrit dans la section 5.2.9 de courant C++0x projet (désolé, n'ont pas de C++03 standard, le projet de je considère que actuelle est n3225.pdf). Il décrit tous les conversions, et je suppose que ce qui n'est pas spécifiquement listé = UB. De sorte qu'il peut vous souffler PC si elle choisit de le faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X