Visual C++ Compiler erzeugt kein Temporary. Bug?
-
Hallo,
aufgrund dieses Threads bzw. meines dortigen Posts ist mir aufgefallen, dass der Visual C++ Compiler kein Temporary beiint(vec.front())erzeugt, was mich irgendwie stutzig gemacht hat. Deswegen hab ich mal ein neues Beispiel gemacht:#include <iostream> using namespace std; int i = 5; void fkt(const int& ref) { cout << '\n' << "Adresse des Temporary: " << &ref; cout << '\n' << "Wert des Temporary: " << ref; i = 10; cout << '\n' << "Wert des Temporary: " << ref; } int main() { cout << '\n' << "Adresse von i : " << &i; fkt( int(i) ); }Visual C++ Compiler:
Adresse von i : 00CF3000 Adresse des Temporary: 00CF3000 Wert des Temporary: 5 Wert des Temporary: 10GCC:
Adresse von i : 0x470000 Adresse des Temporary: 0x28ff1c Wert des Temporary: 5 Wert des Temporary: 5Fazit:
- Visual C++ Compiler erzeugt beiint(i)kein Temporary und die Funktionfktarbeitet mit dem globaleni.
- GCC erzeugt beiint(i)ein Temporary (genauso, wie es sich gehört) und die Funktionfktarbeitet mit einer Kopie des globaleni.Wieder mal ein Bug des Visual C++ Compilers, oder was sagt ihr dazu?
-
Und wo soll da jetzt der Bug sein?
-
SG1 schrieb:
Und wo soll da jetzt der Bug sein?
Dass der eine Compiler bei
int(i)ein temporäres Objekt erzeugt, und der andere nicht.
-
Gugelmoser schrieb:
SG1 schrieb:
Und wo soll da jetzt der Bug sein?
Dass der eine Compiler bei
int(i)ein temporäres Objekt erzeugt, und der andere nicht.Könnte der Compiler das Optimiert haben?
-
Hacker schrieb:
Gugelmoser schrieb:
SG1 schrieb:
Und wo soll da jetzt der Bug sein?
Dass der eine Compiler bei
int(i)ein temporäres Objekt erzeugt, und der andere nicht.Könnte der Compiler das Optimiert haben?
Ich habe mit VS 2010 im Debug-Modus kompiliert. Da ist die Optimierung ja deaktiviert.
-
Und was kommt bei dir bei dem hier raus:
#include <iostream> void func(int&& a) { std::cout << "RVAL"; } void func(int const& a) { std::cout << "REF"; } int i(5); int main() { func( int(i) ); }GCC 4.6.2 sagt RVAL.
-
Gugelmoser schrieb:
SG1 schrieb:
Und wo soll da jetzt der Bug sein?
Dass der eine Compiler bei
int(i)ein temporäres Objekt erzeugt, und der andere nicht.int(i) erzeugt kein temporäres Objekt, ist allerdings ein prvalue.
Wenn ein solches skalares prvalue an eine Referenz gebunden wird, muss ein temporary erzeugt werden (schließlich verweist jede Referenz auf ein Objekt und ein skalares rvalue ist kein Objekt). vc++ tut das offenbar nicht.
-
Und was soll das beweisen? Der Standard sagt, dass RVAL rauskommen soll.
-
camper schrieb:
Gugelmoser schrieb:
SG1 schrieb:
Und wo soll da jetzt der Bug sein?
Dass der eine Compiler bei
int(i)ein temporäres Objekt erzeugt, und der andere nicht.int(i) erzeugt kein temporäres Objekt, ist allerdings ein prvalue.
Wenn ein solches skalares prvalue an eine Referenz gebunden wird, muss ein temporary erzeugt werden (schließlich verweist jede Referenz auf ein Objekt und ein skalares rvalue ist kein Objekt). vc++ tut das offenbar nicht.Sollte ich MS den Bug melden?
-
Wie konnte der Bug jahrelang verborgen bleiben?
Was für ein Fundstück!
-
camper schrieb:
Wenn ein solches skalares prvalue an eine Referenz gebunden wird, muss ein temporary erzeugt werden (schließlich verweist jede Referenz auf ein Objekt und ein skalares rvalue ist kein Objekt).
Fällt das nicht unter as-if?
-
ipsec schrieb:
Fällt das nicht unter as-if?
Solange sich das beobachtete Verhalten nicht ändert. i und das temporäre Objekt sind verschieden, haben aber eine sich überschneidene Lebensdauer.. Also müssen auch deren Adressen verschieden sein. Mit vc++ ist etwas anderes zu beobachten.
-
Anscheinend ist es trotzdem eine Art Optimierung, auch wenn Optimierungen deaktiviert sind.
Konventiert man zum Beispiel zu short, so funktioniert alles wieder:
//... int main() { cout << '\n' << "Adresse von i : " << &i; fkt( short(i) ); cin.get(); }Adresse von i : 00419000 Adresse des Temporary: 0012FEA0 Wert des Temporary: 5 Wert des Temporary: 5Wenn ich
ialsshortdeklariere und dann wie im Ausganspostfkt(int(i));aufrufe, funktioniert es auch noch:Adresse von i : 00419000 Adresse des Temporary: 0012FEA0 Wert des Temporary: 5 Wert des Temporary: 5Wenn ich
ialsshortdeklariere und den geänderten Aufruffkt( short(i));benutze, dann funktioniert es trotzdem:
Adresse von i : 00419000 Adresse des Temporary: 0012FEA0 Wert des Temporary: 5 Wert des Temporary: 5Wenn ich die Veränderungen wie gerade eben lasse und zusätzlich die Funktionissignatur von fkt nach
void fkt( const short& ref)abändere, findet sich wieder der Bug:Adresse von i : 00419000 Adresse des Temporary: 00419000 Wert des Temporary: 5 Wert des Temporary: 10Fazit: Ist anscheinend eine gut gemeinte Optimierung des Compilers, die auch bei abgeschalteter Optimierung wirkt, wenn Typ der Variable, des gewünschten temporären Objekts und des Funktionsargumentes gleich sind.
-
Ich habe eben versucht den Bug zu melden. Will ich einen Thread bei denen im Forum erstellen, bekomme ich aber immer den Fehler "unexpected error". Falls jemand Lust hat, kann derjenige es ja mal versuchen.
-
Language-Extensions deaktiviert?
MSVC erlaubt mit Extensions (die per Default an sind) das Binden von (LValue) Referenzen an RValues. Zumindest bis MSVC 2008, wird bei 2010 dann vermutlich nicht anders sein.
-
hustbaer schrieb:
Language-Extensions deaktiviert?
MSVC erlaubt mit Extensions (die per Default an sind) das Binden von (LValue) Referenzen an RValues. Zumindest bis MSVC 2008, wird bei 2010 dann vermutlich nicht anders sein.
Du hast Recht.
Wenn ich Language-Extensions deaktiviere (Konfigurationseigenschaften --> C/C++ --> Sprache --> Spracherweiterungen deaktivieren = Ja(/Za)) ist alles wieder standardkonform.Danke für den Hinweis, hustbaer.

-
Gugelmoser schrieb:
Wenn ich Language-Extensions deaktiviere (Konfigurationseigenschaften --> C/C++ --> Sprache --> Spracherweiterungen deaktivieren = Ja(/Za)) ist alles wieder standardkonform.
Na super, jetzt spruckt er wegen boost lauter Warnungen aus, weil
/Zaoffensichtlich broken ist.
Das ist doch eine Scheiße. MS raubt mir auch noch den letzten Nerv.
-
Auf jeden Fall kannst du dir jetzt sparen den "Bug" zu reporten - ist schliesslich dokumentiertes und "erwünschtes" Verhalten.