Unter OS X gibt das einfache C ++ - Programm falsche Ergebnisse (die aus den Befehlszeilenoptionen 'c ++ 03' und 'c ++ 11' resultieren).

8

Dieses einfache Programm (wenn es unter Linux kompiliert wird) gibt CORRECTly zwei verschiedene Antworten basierend darauf, ob es mit -std=c++0x kompiliert wurde oder nicht.

Problem: Ich kann dasselbe unter OS X nicht reproduzieren (Mountain Lion, 10.8 SDK). Was vermisse ich?

%Vor%

Um zu sehen, was ich meine, machen Sie Folgendes (auf Linux zuerst, nur um zu sehen, wie es funktionieren soll):

%Vor% %Vor%

Der erste wird eine Hex-Adresse drucken, der zweite wird "Hallo" drucken. Das ist richtiges Verhalten und liegt daran, dass der Operator << zu zwei verschiedenen Dingen aufgelöst wird (es gibt keine Rvalue-Verweise in C ++ 03, also los gehts).

Nun, versuchen Sie dasselbe auf OS X:

%Vor%

(Dies erzeugt korrekt die Hexadezimalausgabe.)

%Vor%

(Ups ... immer noch die Hex-Ausgabe ... Wir sind im C ++ 11x-Modus, aber vielleicht werden die richtigen Header nicht verwendet?)

HINWEIS: Version des Compilers ist hier:

%Vor%

HINWEIS: Dies ist kein C ++ Problem, sondern ein OS X Build Problem. Für diejenigen, die daran interessiert sind, wird der Grund, warum es unterschiedliche Ergebnisse mit C ++ 03 und C ++ 11 erzeugt, in einer der Antworten unten hervorgehoben.

    
Derrick Johnson 20.01.2013, 17:09
quelle

2 Antworten

17

Erstens ist der erwartete Unterschied im Verhalten, weil die operator<<(std::ostream&, const char*) -Überladung (es ist eigentlich eine Funktionsschablonenspezialisierung, aber vorerst keine) einen Parameter vom Typ std::ostream& hat und eine Lvalue-Referenz nur an einen Lvalue und In Ihrem Beispiel ist der Stream ein rvalue, so dass Überladung nicht verwendet werden kann. In C ++ 03 bedeutet das, dass die einzige brauchbare Überladung die std::ostream::operator<<(const void*) -Memberfunktion ist, da Memberfunktionen für rvalue-Objekte aufgerufen werden können, so dass die Zeichenfolge als void* -Adresse in hexadezimaler Schreibweise ausgegeben wird . In C ++ 11 gibt es eine neue operator<<(std::ostream&&, const T&) -Funktionsvorlage, die das Schreiben in Rvalue-Streams ermöglicht und an die operator<<(std::ostream&, const char*) -Überladung weiterleitet, sodass die Zeichenfolge anstelle einer Hexadezimaladresse ausgegeben wird.

Unter GNU / Linux verwenden Sie vermutlich eine ziemlich neue GCC-Version, die sowohl im Compiler (g ++) als auch in der Standardbibliothek (libstdc ++) ziemlich gute Unterstützung für C ++ 11 bietet und daher die operator<<(std::ostream&&, const T&) overload und alles funktioniert einfach.

Unter OS X verwenden Sie wahrscheinlich Clang mit der GCC-Standardbibliothek libstdc ++. Xcode wird standardmäßig mit einer alten Version von GCC ausgeliefert (4.2) und die Standardbibliothek von GCC 4.2 unterstützt nicht C ++ 11, also nicht die operator<< Überladung für Rvalue Streams. Die Verwendung von -std=c++0x weist Clang an, C ++ 11-Sprachfunktionen zu unterstützen (wie z. B. rvalue-Referenzen), macht aber die Bibliothek von GCC 4.2 nicht zu C ++ 11-Code, der nicht einmal ein Augenzwinkern im Standardkommitee war als GCC 4.2 veröffentlicht wurde. Anstatt eine nicht-prehistorische libstdc zu verschicken, schrieb Apple stattdessen eine eigene Standard-Bibliotheks-Implementierung, um LLVM- und Clang-Projekten zu folgen. Wenn -stdlib=libc++ verwendet wird, wird clang angewiesen, diese libc ++ - Standardbibliotheksimplementierung anstelle des alten libstdc ++ zu verwenden. Da libc ++ vor kurzem geschrieben wurde, hat es die operator<< Überladung für rvalue Referenzen.

    
Jonathan Wakely 04.01.2013, 02:51
quelle
6

Es scheint ein Problem zu sein, wenn callg libstdc ++ standardmäßig verwendet, anstatt libc ++. Kompilieren wie folgt: clang++ -std=c++0x -stdlib=libc++ test.cpp führt zu der erwarteten Ausgabe.

    
Jon Shier 04.01.2013 02:02
quelle