static_cast thread safe?
-
Cast ist ein Synonym für
explizite Typkonvertierung. Das brauchst du, wenn der Compiler1. schlicht nicht in der Lage ist, eine implizite Typkonvertierung durchzuführen.
int main() { int x = 0; const int& cref = x; int& ref = cref; // Er kann nicht implizit konvertieren. [const_cast ist hier ok, da kein const auf höchster Ebene] }2. sich nicht entscheiden kann, zu welchem Typ er konvertieren soll.
void fkt( float f ) { } void fkt( double d ) { } int main() { fkt( 2 ); // Er kann sich nicht entscheiden. }3. dir eine Warnung gibt, die du gelesen, verstanden und beseitigen möchtest, da es in deinem Fall zu keinem Schaden kommt.
int main() { unsigned x = 8; unsigned char uc = x; // Warnung: Eventuell gibt es einen Informationsverlust. }Wie in dem Buch richtig stehst, sollst du C++-Cast-Operatoren verwenden,
1. da sie Typsicherheit bieten, d.h. Fehler können zur Kompilierzeit abgefangen werden. (Du kannst z.B. nicht aus Versehen const wegcasten)
2. die anschauliche Syntax dir sagt, was passiert. (beispielsweise sagt dir const_cast, dass das const verschwindet). Ein C-Cast sagt dir das nicht. Bei einem C-Cast kann alles mögliche passieren, z.B. kann gleichzeitg static_cast + const_cast passieren.
3. die anschauliche Syntax dir ermöglicht, den Quellcode nach Casts zu durchsuchen. Suche nach "_cast".
Auch wenn es die guten C++-Cast-Operatoren gibt, solltest du sparsam damit umgehen. Bzw.
const_cast,dynamic_castundreinterpret_castsollten sowieso so gut wie nie vorkommen.1. Wenn du
dynamic_castbrauchst, hast du höchst wahrscheinlich einen Designfehler gemacht. Salopp gesagt: Kein Designfehler --> Keindynamic_castnötig.2. Willst
const_castverwenden, solltest du dich fragen, wieso du das willst. Manche leute verwenden es, um Compilerfehler zu beseitigen. Dass das nicht Sinn und Zweck ist und außerdem sau gefährlich ist, sollte klar sein.const_castdarfst du nur dann verwenden, wenn es auf höchster Ebene kein const gibt. Ansonsten hast du UB.reinterpret_castist sau gefährlich. Da musst du schon genau wissen, was du sonst, ansonsten landest du schnell bei UB.
-
Vor allem ist reinterpret_cast meistens nichtmal platformunabhängig.
Ich selbst kenne einen Anwendungsfall für const_cast, den erklärt Scott Meyers in seinem Buch "Effective C++". Sehr interessant zu lesen.
-
Fuchs aus dem Wald schrieb:
Hi,
ich bin eben in eine Diskussion geraten und zwar ging es darum ob ein static_cast thread safe ist. Ich lese grade das Buch "Der C++ Programmierer" und bin dort auf diesen gestoßen. Allerdings hab ich vorher immer ein c-cast benutzt. Im Buch wird nun empfohlen den static_cast zu benutzen ich also mal nachgefragt und es wurde mir gesagt das static_cast nicht thread safe ist.Eine sinnlose Behauptung, wenn sie nicht erläutert wird. Threadsicherheit ist auch keine Funktion der Form eines Ausdrucks.
-
Vielen Dank für eure Informationen! Das war sehr lehrreich! Im Buch wurde das bis jetzt noch nicht genauer erklärt denke das wird aber noch kommen. EDIT: Jo kommt unter 7.9

Der link und die Erklärung von out waren super. Das von Scott Meyers hab ich über google auch schon mal gefunden aber leider nicht lesen können. Müsste ja das Buch haben.
-
Fuchs aus dem Wald schrieb:
Der link und die Erklärung von out waren super. Das von Scott Meyers hab ich über google auch schon mal gefunden aber leider nicht lesen können. Müsste ja das Buch haben.

Ungefähr so:
class Klasse { const object& foo() const { // ... } object& foo() { // Nutze Klasse::foo() const return const_cast<object&>(const_cast<const Klasse*>(this)->foo()); } };Man spart sich eine Implementierung, allerdings halte ich es in den meisten Fällen für angebracht, einen anderen weg zu suchen.
-
Der innere const_cast sollte ein static_cast sein.
reinterpret_cast ist super nuetzlich zur Serialisierung. Davon grundsaetzlich abzuraten halte ich fuer Mist.
-
reinterpret_cast ist super nützlich zur platformabhängigen, compilerversionabhängigen und compilereinstellungsabhängigen Serialisierung.
-
ftfy schrieb:
reinterpret_cast ist super nützlich zur platformabhängigen, compilerversionabhängigen und compilereinstellungsabhängigen Serialisierung.
Ich finde es toll, dass du Code schreibst, der auf jedem noch so besonderen Mikrocontroller mit C++-Implementierung laeuft. Das ist mir bei meinen Programmen aber relativ egal.
Auf meinen Ziel-Plattformen ist:
- ein (u)intN_t genau N Bytes gross, in little-endian gespeichert und falls signed im 2er Komplement
- ein float/double in einem IEEE754-konformen FormatAusserdem ist reinterpret_cast flott. Mag sein, dass der Compiler das optimieren kann, wenn ich Bitoperationen verwende. Spaetestens bei Fliesskommazahlen wirds dann aber schwer. Flotter als reinterpret_cast gehts wohl kaum. Zumal das genau das ausdrueckt, was ich tun moechte: "Gib mir die Bytes von diesem Ding."
Daher:
Kellerautomat schrieb:
Davon grundsaetzlich abzuraten halte ich fuer Mist.
Auf deinen sinnlosen Rechtschreibflame gehe ich mal nicht ein.
-
Mal nochmal für mich: static_cast für native Typen ist eine Uminterpretation eines Wertes und kostet somit keine Laufzeit und ist somit immer threadsafe?
-
Eisflamme schrieb:
Mal nochmal für mich: static_cast für native Typen ist eine Uminterpretation eines Wertes und kostet somit keine Laufzeit und ist somit immer threadsafe?
Nein.
Bei double -> int muss gerechnet werden, weil die Bitinterpretation anders ist.
Ebenso int -> long, weil die oberen Bits genullt sein müssen.
float -> double ebenfalls.
signed -> unsigned hingegen nicht (Zweierkomplement vorausgesetzt)Kostet aber nur minimal Laufzeit.
Threadsafe hat gar nichts damit zu tun. Schon das Lesen einer int-Variable ist nicht threadsafe (atomar)
-
Habe gerade überlegt, wieso das dann nichts damit zu tun hat. Da fiel mir ein, dass man den Wert ja auch irgendwo benutzen muss, weil der Cast sonst sinnlos ist. Alles klar

-
Eisflamme schrieb:
Habe gerade überlegt, wieso das dann nichts damit zu tun hat. Da fiel mir ein, dass man den Wert ja auch irgendwo benutzen muss, weil der Cast sonst sinnlos ist. Alles klar

Wow genau dieser Satz wird hier Augen öffnen.

Danke an die vielen Antworten! Hat mich weiter gebracht.
-
eehnope schrieb:
Eisflamme schrieb:
Mal nochmal für mich: static_cast für native Typen ist eine Uminterpretation eines Wertes und kostet somit keine Laufzeit und ist somit immer threadsafe?
Nein.
Bei double -> int muss gerechnet werden, weil die Bitinterpretation anders ist.
Ebenso int -> long, weil die oberen Bits genullt sein müssen.
float -> double ebenfalls.
signed -> unsigned hingegen nicht (Zweierkomplement vorausgesetzt)Kostet aber nur minimal Laufzeit.
Ich denke, in vielen Fällen kostet es sogar keine Laufzeitdifferenz, denn x87 FPUs haben 80bit große Register.
Bei double->int muss in ein Integer, beim Speichern in einer double-Variable muss von 80 bit auf 64 umgerechnet werden (FIST statt FST).
Oft wird der Geschwindigkeitsverlust sogar unter einem Takt liegen, eine Differenz auf die man selbst bei starker Optimierung verzichten kann.
-
Ich verwende reinterpret_cast für 2 Anwendungsfälle:
1. Bei meinen Gamehacks:
uintptr_t const IS_SWIMMING_ADDRESS = 0xDEADBEEF; *reinrterpret_cast<uint32_t>(IS_SWIMMING_ADDRESS) = true;2. mit std::aligned_storage
-
Ethon schrieb:
mit std::aligned_storage
static_cast?
-
Sone schrieb:
Ethon schrieb:
mit std::aligned_storage
static_cast?static_cast<Foo*>(static_cast<void*>(bar));Finde ich nicht wirklich besser.

-
Ethon schrieb:
static_cast<Foo*>(static_cast<void*>(bar));Missverständnis.