Sowohl static_cast als auch reinterpret_cast scheinen gut zu funktionieren, um void * in einen anderen Zeigertyp umzuwandeln. Gibt es einen guten Grund, einander vorzuziehen?
Sowohl static_cast als auch reinterpret_cast scheinen gut zu funktionieren, um void * in einen anderen Zeigertyp umzuwandeln. Gibt es einen guten Grund, einander vorzuziehen?
Antworten:
Verwendungstatic_cast
: Es ist die engste Besetzung, die genau beschreibt, welche Konvertierung hier vorgenommen wird.
Es gibt ein Missverständnis, dass die Verwendung reinterpret_cast
besser zusammenpassen würde, da dies bedeutet, dass die Typensicherheit vollständig ignoriert und nur von A nach B geworfen wird.
Dies beschreibt jedoch nicht die Wirkung von a reinterpret_cast
. Hat vielmehr reinterpret_cast
eine Reihe von Bedeutungen, für die alle besagen, dass „das von durchgeführte Mapping reinterpret_cast
implementierungsdefiniert ist“. [5.2.10.3]
Aber im besonderen Fall des Castings von void*
bis T*
zum Mapping ist der Standard völlig genau definiert; nämlich einem typlosen Zeiger einen Typ zuzuweisen, ohne dessen Adresse zu ändern.
Dies ist ein Grund zu bevorzugen static_cast
.
Darüber hinaus und wohl wichtiger ist die Tatsache, dass jede Verwendung von reinterpret_cast
geradezu gefährlich ist, da sie alles wirklich in etwas anderes umwandelt (für Zeiger), während sie static_cast
viel restriktiver ist und somit ein besseres Schutzniveau bietet. Dies hat mich bereits vor Fehlern bewahrt, bei denen ich versehentlich versucht habe, einen Zeigertyp in einen anderen zu zwingen.
Das ist eine schwierige Frage. Einerseits macht Konrad einen hervorragenden Punkt in Bezug auf die Spezifikationsdefinition für reinterpret_cast , obwohl es in der Praxis wahrscheinlich dasselbe tut. Wenn Sie dagegen zwischen Zeigertypen wechseln (wie dies beispielsweise bei der Indizierung im Speicher über ein char * üblich ist), generiert static_cast einen Compilerfehler und Sie müssen ohnehin reinterpret_cast verwenden .
In der Praxis verwende ich reinterpret_cast, weil es die Absicht der Cast-Operation besser beschreibt. Sie könnten sich durchaus dafür einsetzen, dass ein anderer Operator nur Zeiger-Neuinterpretationen festlegt (die die gleiche zurückgegebene Adresse garantieren), aber es gibt keine im Standard.
reinterpret_cast
!
Ich schlage vor, immer die schwächste Besetzung zu verwenden.
reinterpret_cast
kann verwendet werden, um einen Zeiger auf a zu werfen float
. Je strukturbrechender die Besetzung ist, desto mehr Aufmerksamkeit erfordert ihre Verwendung.
Im Falle von char*
würde ich eine Besetzung im C-Stil verwenden, bis wir welche haben reinterpret_pointer_cast
, weil sie schwächer ist und nichts anderes ausreicht.
float f = *reinterpret_cast<const float*>(&p);
float
, was falsch ist. Der Ausdruck Abgüsse void **
zu const float *
und verwendet dann einen dereferenzieren Betrieb (das ist kein cast), zu konvertieren const float *
zu float
.
Meine persönliche Präferenz basiert auf Code-Kenntnissen wie folgt:
void* data = something;
MyClass* foo = reinterpret_cast<MyClass*>(data);
foo->bar();
oder
typedef void* hMyClass; //typedef as a handle or reference
hMyClass = something;
const MyClass& foo = static_cast<MyClass&>(*hMyClass);
foo.bar();
Am Ende machen beide dasselbe, aber static_cast scheint in einer Middleware-App-Umgebung angemessener zu sein, während eine Neuinterpretation der Besetzung eher etwas ähnelt, das Sie meiner Meinung nach in einer Bibliothek auf niedrigerer Ebene sehen würden.