2013-02-11 22 views
8

Ich habe Schwierigkeiten, die Reihenfolge der Aufrufe in dem Code unten zu verstehen. Ich hatte erwartet, die Ausgabe unterReihenfolge der Ausführung im Operator <<

A1B2 

zu sehen, während ich sehen kann, dass die Ausgabe ich erhalte, ist

BA12 

Ich dachte, dass der Anruf std::cout<< b->fooA() << b->fooB() << std::endl gleichkam

std::cout.operator<<(b->fooA()).operator<< (b->fooB()) 

zu nennen aber ich kann sehen, dass dies nicht der Fall ist. Können Sie mir helfen, besser zu verstehen, wie dies funktioniert und die Beziehung mit der globalen operator<<? Wird dieser letzte jemals in dieser Reihenfolge aufgerufen?

Grüße

AFAG

#include <iostream> 

    struct cbase{ 
     int fooA(){ 
      std::cout<<"A"; 
      return 1; 
     } 
     int fooB(){ 
      std::cout <<"B"; 
      return 2; 
     } 
    }; 

    void printcbase(cbase* b){ 
     std::cout << b->fooA() << b->fooB() << std::endl; 
    } 

    int main(){ 
     cbase b; 
     printcbase(&b); 
    } 
+3

Sie haben Recht, wenn Sie denken, dass es dem entspricht. Sie machen jedoch die falsche Annahme, dass es eine klar definierte Reihenfolge der Bewertung gibt. Es ist nicht.Das ist alles. –

+0

Reihenfolge der Teilausdruck-Auswertung ist hier nicht garantiert (und es * muss * ein Duplikat sein, aber ich kann gerade keine gute kanonische Frage finden) –

+0

'AB12' oder' BA12' sind mögliche Ausgaben. 'A1B2' ist nicht (hoffentlich). – jrok

Antwort

8

Der Compiler kann die Funktion printcbase() wie diese bewerten:

void printcbase(cbase* b){ 
    int a = b->FooA(); // line 1 
    int b = b->FooB(); // line 2 
    std::cout << a;  // line 3 
    std::cout << b;  // line 4 
    stc::cout << std::endl; 
} 

oder einige von vielen permutatins von Linien markiert als 1 - 4. Sie sind nur garantiert, dass die Linie 1 vor der Linie 3 und die Linie 2 vor der Linie 4 (und natürlich Linie 3 vor der Linie 4) erfolgt. Standard sagt nicht mehr und tatsächlich können Sie unterschiedliche Ergebnisse mit verschiedenen C++ - Compilern erwarten.

+0

eine Einschränkung fehlt Zeile 3 ist vor Zeile 4. –

+0

Nun, das ist so offensichtlich, es war nicht ein Punkt meines Denkens. Ich werde es hinzufügen. Vielen Dank. – mity

4

Die Reihenfolge der Ausführung von << ist gut definiert, aber die Reihenfolge der Auswertung von Unterausdrücken ist in C++ nicht definiert. This article and the C code example veranschaulicht das Problem, das Sie erwähnten.

BA12 und AB12 sind beide richtig. Im folgenden Code:

std::cout<< b->fooA() << b->fooB() 

1 wird vor 2 erscheinen aber A erscheinen könnte vor oder nach B da die Compiler nicht versprechen, ob es fooA oder fooB ersten auswertet.

1

Die Shift-Operatoren sind linksassoziativ; a << b << c wird als (a << b) << c gelesen, was bedeutet, dass, wenn a von einem Typ mit Mitglied benutzerdefiniert operator<< ist (und diesen Typ zurückgibt), der Ausdruck lautet a.operator<<(b).operator<<(c). Wenn stattdessen ein freies operator<< verwendet wird, dann lautet dies operator<<(operator<<(a, b), c).

So ist die Auswertung von a << b wird vor der Auswertung von (a << b) << c sequenziert, aber es gibt keine Sequenzierung Abhängigkeit zwischen der Bewertung von b und c:

a << b << c[1] 
|   | 
a << b[2] | 
| | c[5] 
a[3] b[4] 

Wenn wir die Nebenwirkungen wie oben nummerieren, dann ist die Nebenwirkungen können wie folgt sequenziert werden:

54321 
53421 
45321 
43521 
43251 
35421 
34521 
34251