web-dev-qa-db-fra.com

Lors de la conversion d'un pointeur void en un pointeur de type spécifique, quel symbole de conversion est le meilleur, static_cast ou reinterpret_cast?

Duplicata possible:
Dois-je utiliser static_cast ou reinterpret_cast lors de la diffusion d'un void * vers quoi que ce soit

Dans ce programme, j'ai un void * en tant que paramètre et que vous souhaitez convertir en un type spécifique. Mais je ne sais pas quel "symbole de casting" utiliser. Tous les deux static_cast ou reinterpret_cast travail. Quel est le meilleur? Lequel le Standard C++ recommande-t-il?

typedef struct
{
    int a;
}A, *PA;

int foo(void* a)                // the real type of a is A*
{
    A* pA = static_cast<A*>(a); // or A* pA = reinterpret_cast<A*>(a);?
    return pA->a;
}

Voici

A* pA = static_cast<A*>(a);

ou

A* pA = reinterpret_cast<A*>(a);

plus approprié?

36
Sid Zhang

Le static_cast Est plus approprié pour convertir un void* En un pointeur d'un autre type.

static_cast Est la distribution de choix lorsqu'il existe une conversion naturelle et intuitive entre deux types qui n'est pas nécessairement garantie de fonctionner au moment de l'exécution. Par exemple, vous pouvez utiliser static_cast Pour convertir des pointeurs de classe de base en pointeurs de classe dérivés, ce qui est une conversion qui a du sens dans certains cas mais qui ne peut pas être vérifiée avant l'exécution. De même, vous pouvez utiliser static_cast Pour convertir d'un int en char, qui est bien défini mais peut entraîner une perte de précision lors de son exécution.

reinterpret_cast, D'un autre côté, est un opérateur de casting conçu pour effectuer des conversions qui ne sont fondamentalement ni sûres ni portables. Par exemple, vous pouvez utiliser reinterpret_cast Pour passer d'un void * À un int, ce qui fonctionnera correctement si votre système possède justement sizeof (void*)sizeof (int). Vous pouvez également utiliser reinterpret_cast Pour convertir un float* En un int* Ou vice-versa, qui est spécifique à la plate-forme car les représentations particulières de floats et ints ne sont pas garantis d'avoir quelque chose en commun les uns avec les autres.

En bref, si jamais vous vous retrouvez en train de faire une conversion dans laquelle le transtypage est logiquement significatif mais peut ne pas nécessairement réussir au moment de l'exécution, évitez reinterpret_cast. static_cast Est un bon choix si vous avez une connaissance préalable que la distribution va fonctionner au moment de l'exécution et communique au compilateur "Je sais que cela pourrait ne pas fonctionner, mais au moins cela a du sens et j'ai un raison de croire qu'il fera correctement la bonne chose à l'exécution. " Le compilateur peut ensuite vérifier que la conversion est entre des types liés, signalant une erreur de compilation si ce n'est pas le cas. L'utilisation de reinterpret_cast Pour ce faire avec les conversions de pointeurs contourne complètement le contrôle de sécurité au moment de la compilation.

Il y a quelques cas où vous voudrez peut-être utiliser un dynamic_cast Au lieu d'un static_cast, Mais ceux-ci impliquent principalement des transtypages dans une hiérarchie de classes et (rarement) concernent directement void* .

Quant à celui qui est préféré par la spécification, ni l'un ni l'autre n'est trop mentionné comme "le bon à utiliser" (ou du moins, je ne me souviens pas que l'un d'eux ait été mentionné de cette façon.) Cependant, je pense que la spécification veut que vous le fassiez utilisez static_cast sur reinterpret_cast. Par exemple, lorsque vous utilisez une distribution de style C, comme dans

A* ptr = (A*) myVoidPointer;

L'ordre des opérateurs de transtypage essayés essaie toujours d'utiliser un static_cast Avant un reinterpret_cast, Ce qui est le comportement que vous souhaitez puisque reinterpret_cast N'est pas garanti d'être portable.

50
templatetypedef

Utilisation static_cast pour ça. Seulement dans les cas les plus rares où il n'y a pas d'autre moyen, utilisez reinterpret_cast.

1
Asha

Vous avez probablement obtenu que void* avec conversion implicite, vous devez donc utiliser static_cast car il est le plus proche de la conversion implicite.

0
sharptooth

Si vous effectuez un cast le long d'une hiérarchie de classes, utilisez dynamic_cast - il vérifie que l'objet réel est compatible avec le type vers lequel vous effectuez le cast.

0
Ken Wayne VanderLinde