2013-05-09 4 views
5

Betrachten Sie eine kleine Einheit TestfallDereferenziere und Rückkehr durch Verweis

struct A 
{ 
    virtual void func(){} 
    A& foo() 
    { 
    A *obj = reinterpret_cast<A*>(0xdeadbeef); 
    return *obj; //1 
    } 
}; 

int main() 
{ 
    A obj = obj.foo(); 
} 

In Zeile 1 ist es Implementierung definiert/nicht spezifiziert, dass die Ehrerbietung nicht passieren würde, wie wir durch Bezugnahme zurückkehren und das Programm würde nicht abstürzen, wenn ein expliziter Zugriff auf das auf Objekt verwiesen wird nicht gemacht?

Ich hatte Streit mit einem meiner Kollegen, wobei er erwähnt, dass der Compiler in den meisten Fällen die Dereferenz von obj optimieren würde, wie wir es per Referenz zurückgeben und dieser Code würde nicht abstürzen?

Dank

+0

Mein Verständnis ist: Der Compiler ist nicht verpflichtet, 1) Code auszuführen, der nichts passiert 2) Code ausführen, der ein undefiniertes Verhalten erzeugt: http://blog.llvm.org/2011/05/what-every- c-programmer-sollte-wissen_14.html – Patashu

+0

Auch ich glaube, das Verhalten ist nicht definiert und wir sollten uns in diesem Fall nicht auf die zugrunde liegende Implementierung verlassen. –

+2

Es ist undefiniertes Verhalten und Sie sollten sich nie auf undefiniertes Verhalten verlassen, was Sie tun, was Sie denken, ja. Aber es wird auch nicht unbedingt zum Absturz kommen, wenn der Compiler entscheidet, dass es sich um einen toten Code oder um einen undefinierten Code handelt, für den aus akademischer Perspektive kein Code produziert werden sollte. – Patashu

Antwort

4

ich zerlegen den Code in MS VC8.0, und die Dinge finden interessanter:

006D48D6 mov   dword ptr [ebp-8],ecx 
    A *obj = reinterpret_cast<A*>(0xdeadbeef); 
006D48D9 mov   dword ptr [obj],0DEADBEEFh 
     return *obj; //1 
006D48E0 mov   eax,dword ptr [obj] //2 
    } 
006D48E3 mov   esp,ebp 
006D48E5 pop   ebp 
006D48E6 ret  

// 2 zeigt, dass die Adresse des obj an das EAX-Register als Rückgabewert setzen nur .

006D39FC lea   ecx,[ebp-190h] 
006D3A02 call  A::foo (6A8C12h) 
006D3A07 push  eax //3 
006D3A08 lea   ecx,[ebp-190h] 
006D3A0E call  A::A (6B89BEh) 

eax ist 0xdeadbeef und Push-to-Stack als temporäre lokale Variable tut. Dann nennen wir den Kopierkonstruktor (was trivial ist). All diese Aktionen passieren nur die Adresse (was illegal ist, aber das Programm kümmert sich nicht) .Da die A-Struktur kein Mitglied hat, das an ein spezifisches Objekt gebunden ist, und das Programm wird nicht versuchen, ein spezifisches Objekt durch Dereferenzierung zu finden, wenn es nicht funktioniert. t brauchen. Also diese Bombe wurde nicht gefeuert.

 A *obj = reinterpret_cast<A*>(0xdeadbeef); 
     A tmp ; 
     temp = *obj; 

Auch das ist in Ordnung, weil operator = auch durch Bezugnahme, die in der Tat die Adresse fest passiert passieren wird Sie eine Membervariable hinzufügen, wird es scheitern, weil sie versuchen, das Mitglied zu finden und zu kopieren.

+2

+1 zum Eingraben, obwohl es die Frage nicht beantwortet. – qdii