265 Stimmen

Sollte ich static_cast oder reinterpret_cast beim Casting eines void* zu was auch immer verwenden

Beide static_cast y reinterpret_cast scheinen beim Gießen gut zu funktionieren void* auf einen anderen Zeigertyp. Gibt es einen guten Grund, den einen dem anderen vorzuziehen?

82 Stimmen

@anon Offenbar haben Sie noch nie mit POSIX-Threads gearbeitet.

10 Stimmen

@user470379 Wow... das ist der Grund, warum ich bei SO auf diese Frage gestoßen bin! Ausgezeichnete Beobachtung :-).

211voto

Konrad Rudolph Punkte 503837

Verwenden Sie static_cast : Es ist die engste Besetzung, die genau beschreibt, was hier umgewandelt wird.

Es ist ein Missverständnis, dass die Verwendung von reinterpret_cast wäre eine bessere Übereinstimmung, weil es bedeutet "völlig ignorieren Typ Sicherheit und nur von A nach B werfen".

Dies beschreibt jedoch nicht die Wirkung einer reinterpret_cast . Vielmehr, reinterpret_cast hat eine Reihe von Bedeutungen, für die alle gilt, dass "die Abbildung, die von reinterpret_cast ist implementierungsabhängig." [5.2.10.3]

Aber in dem besonderen Fall des Gießens aus void* à T* die Zuordnung ist durch den Standard vollständig definiert, nämlich einem typlosen Zeiger einen Typ zuzuweisen, ohne seine Adresse zu ändern.

Dies ist ein Grund, die static_cast .

Hinzu kommt - und das ist wohl noch wichtiger -, dass jede Verwendung von reinterpret_cast ist geradezu gefährlich, weil es alles in alles andere umwandelt (bei Zeigern), während static_cast ist viel restriktiver und bietet somit einen besseren Schutz. Dies hat mich bereits vor Fehlern bewahrt, bei denen ich versehentlich versucht habe, einen Zeigertyp in einen anderen zu zwingen.

70voto

templatetypedef Punkte 343693

El static_cast ist besser geeignet für die Umwandlung einer void* auf einen Zeiger eines anderen Typs.

static_cast ist das Mittel der Wahl, wenn es eine natürliche, intuitive Konvertierung zwischen zwei Typen gibt, bei der nicht unbedingt gewährleistet ist, dass sie zur Laufzeit funktioniert. Sie können zum Beispiel verwenden static_cast um Zeiger von Basisklassen in Zeiger von abgeleiteten Klassen zu konvertieren, eine Konvertierung, die in einigen Fällen sinnvoll ist, aber erst zur Laufzeit überprüft werden kann. In ähnlicher Weise können Sie static_cast zur Konvertierung von einer int zu einer char die wohldefiniert ist, aber bei der Ausführung zu einem Verlust an Präzision führen kann.

reinterpret_cast ist dagegen ein Gießereibetrieb, der für Umwandlungen konzipiert ist, die grundsätzlich nicht sicher oder nicht tragbar sind. Zum Beispiel können Sie mit reinterpret_cast zur Konvertierung von einer void * zu einer int , die korrekt funktioniert, wenn Ihr System zufällig über sizeof (void*)sizeof (int) . Sie können auch verwenden reinterpret_cast zur Umwandlung einer float* zu einer int* oder umgekehrt, was plattformspezifisch ist, da die jeweiligen Darstellungen von float s und int s haben nicht unbedingt etwas miteinander zu tun.

Kurz gesagt, wenn Sie jemals eine Konvertierung durchführen, bei der der Cast logisch sinnvoll ist, aber zur Laufzeit nicht unbedingt erfolgreich sein wird, vermeiden Sie reinterpret_cast . static_cast ist eine gute Wahl, wenn man im Voraus weiß, dass der Cast zur Laufzeit funktionieren wird, und dem Compiler mitteilt: "Ich weiß, dass dies vielleicht nicht funktioniert, aber zumindest macht es Sinn und ich habe einen Grund zu glauben, dass es zur Laufzeit das Richtige tun wird." Der Compiler kann dann überprüfen, ob der Cast zwischen verwandten Typen erfolgt, und meldet einen Kompilierfehler, wenn dies nicht der Fall ist. Verwendung von reinterpret_cast dies mit Zeigerumwandlungen zu tun, umgeht die Sicherheitsprüfung zur Kompilierzeit vollständig.

Es gibt ein paar Umstände, unter denen Sie eine dynamic_cast anstelle einer static_cast aber diese beinhalten meist Abwandlungen in einer Klassenhierarchie und betreffen (nur selten) direkt void* .

Was die Frage anbelangt, welche der beiden von der Spezifikation bevorzugt wird, so wird keine von beiden ausdrücklich als "die Richtige" erwähnt (oder zumindest kann ich mich nicht daran erinnern, dass eine der beiden auf diese Weise erwähnt wurde). static_cast über reinterpret_cast . Wenn Sie zum Beispiel einen Cast im C-Stil verwenden, wie in

A* ptr = (A*) myVoidPointer;

Die Reihenfolge der Casting-Operatoren, die ausprobiert wird, versucht immer, eine static_cast vor einer reinterpret_cast Das ist das gewünschte Verhalten, denn reinterpret_cast ist nicht garantiert tragbar.

2 Stimmen

Zur Klarstellung: Was der Autor hier mit " static_cast ... ist nicht unbedingt garantiert, dass es zur Laufzeit funktioniert" heißt: "Ihr Programm könnte später abstürzen." Wenn Sie static_cast von einem Basistyp zu einem abgeleiteten Typ, ist es wird zur Laufzeit "funktionieren" (d.h. Sie werden no eine Ausnahme oder eine NULL Zeiger), aber das Ergebnis kann auf den falschen Speicherplatz zeigen, wenn Mehrfachvererbung im Spiel ist. (Siehe diese Antwort für weitere Einzelheiten). Nur dynamic_cast führt eine Laufzeitprüfung (mit RTTI) durch und schlägt fehl, wenn der Cast ungültig ist.

12voto

Nick Punkte 6782

Das ist eine schwierige Frage. Einerseits macht Konrad einen ausgezeichneten Punkt über die Definition der Spezifikation für uminterpretieren_gießen obwohl es in der Praxis wahrscheinlich das Gleiche bewirkt. Andererseits, wenn Sie zwischen Zeigertypen casten (wie es z.B. bei der Indexierung im Speicher über ein char* üblich ist), statisch_gecastet erzeugt einen Compilerfehler und Sie sind gezwungen, die uminterpretieren_gießen sowieso.

In der Praxis verwende ich uminterpretieren_gießen weil es die Absicht der Cast-Operation besser beschreibt. Man könnte sicherlich ein Argument für einen anderen Operator vorbringen, um nur Zeigerumwandlungen zu bezeichnen (die garantiert dieselbe Adresse zurückgeben), aber es gibt keinen in der Norm.

8 Stimmen

" ein anderer Operator, der nur Zeiger-Reinterpretationen angibt (die garantiert dieselbe Adresse zurückgeben) " Umarmung? Dieser Betreiber ist reinterpret_cast !

4 Stimmen

@curiousguy Nach dem Standard stimmt das nicht. reinterpret_cast garantiert NICHT, dass die gleiche Adresse verwendet wird. Nur, dass wenn man reinterpret_cast von einem Typ zu einem anderen und dann wieder zurück erhalten Sie dieselbe Adresse zurück, mit der Sie begonnen haben.

3voto

sharptooth Punkte 162790

Wahrscheinlich haben Sie das void* mit impliziter Konvertierung, daher sollten Sie static_cast weil sie der impliziten Umwandlung am nächsten kommt.

2voto

anton_rh Punkte 6967

Gießen nach und von void* mit static_cast und mit reinterpret_cast identisch ist. Siehe die Antwort unter die Verbindung . Aber normalerweise static_cast ist vorzuziehen, da es sich um eine engere und im Allgemeinen (aber nicht in diesem speziellen Fall) sicherere Umwandlung handelt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X