2017-12-06 12 views
0

ich dieses Beispiel lautete:Copy-Konstruktor und kaskadierte Funktion aufruft

#include <cstdlib> 
#include <iostream> 
#include <istream> 
#include <ostream> 
using namespace std; 
class Weight { 
    int k; 
    char a[100]; 
public: 
    Weight(int kilos = 0) 
     :k(kilos) {} 
    Weight(const Weight& w) 
     : k(w.k) { 
     for(int i = 0; i < 100; ++i) this->a[i] = 'a'; 
     cout << "WCC\n"; 
    } 
    friend Weight operator+(const Weight& a, const Weight& b); 
    Weight& operator=(const Weight & w) { 
     this->k = w.k; 
     return *this; 
    } 
    friend ostream& operator<<(ostream&, const Weight&); 
}; 
Weight operator+(const Weight& a, const Weight& b) { 
    cout << "FP\n"; 
    int newkg = a.k + b.k; 
    return Weight(newkg); 
} 
ostream& operator<<(ostream& out, const Weight& w) { 
    out << w.k << " KGs"; 
    return out; 
} 
class Container{ 
    Weight w; 
    static Weight totalW; 
    static int count; 
public: 
    Container(){++count;} 
    ~Container(){cout << "CD\n";} 
    Container& add(Weight weight) { 
     this->w = this->w + weight; 
     totalW = totalW + weight; 
     cout << "Just added a new item that weighs " << weight << endl; 
     return *this; 
    } 
    static void print() { 
     cout << "We have " << count << " Containers with a total weight " 
       << totalW << endl; 
    } 
    friend ostream& operator<<(ostream&, const Container&); 
}; 
Weight Container::totalW; 
int Container::count = 0; 
ostream& operator<<(ostream& out, const Container& c){ 
    out << "This container's " << c.w; 
    return out; 
} 
int main(int argc, char** argv) { 
    Container c1; 

    Weight *w1 = new Weight(1); 
    Weight *w2 = new Weight(2); 
    Weight *w3 = new Weight(3); 

    cout << "Adding items to container...\n"; 
    c1.add(*w1).add(*w2).add(*w3); 

    cout << c1 << endl; 

    Container::print(); 
    return 0; 
} 

Und ich habe diese Ausgabe:

Adding items to container... 
WCC 
WCC 
WCC 
FP 
FP 
Just added a new item that weighs 1 KGs 
FP 
FP 
Just added a new item that weighs 2 KGs 
FP 
FP 
Just added a new item that weighs 3 KGs 
This container's 6 KGs 
We have 1 Containers with a total weight 6 KGs 
CD 

Sie können sehen, dass die Kopie Konstruktor für die Gewichtsklasse dreimal genannt wurde (Ausgabezeilen 2-4) bevor eine der kaskadierten Funktionen aufgerufen wurde. Ich dachte immer, dass der Funktionsaufruf ganz links ausgeführt wird, bevor ein Kopierkonstruktor zum Einrichten des zweiten Funktionsaufrufs aufgerufen wird.

Um genauer zu sein, dachte ich das was hätte passieren sollen: WCC -> c1.add (* w1) -> WCC -> .add (* w2) -> WCC -> .add (* w3) .

Ich dachte, das war notwendig, weil das Funktionsargument im Stapelrahmen der Funktion gespeichert wird. Daher muss ein Stack-Frame eingerichtet werden, bevor der Kopierkonstruktor für das Argument aufgerufen wird. Anscheinend bin ich falsch.

Das lässt mich denken, dass Funktionsargumente irgendwo anders als der Stapelrahmen gespeichert werden. Also wo?

Den schrecklichen Codierungsstil nicht stören. Dies ist offensichtlich nicht im Produktionscode vorgesehen.

+0

'add()' nimmt seinen Parameter nach Wert. Dazu muss eine Kopie des Arguments erstellt werden, bevor die Funktion aufgerufen wird. Die Reihenfolge der Auswertung von Teilausdrücken innerhalb eines Ausdrucks ist nicht spezifiziert. Hier wählte der Compiler alle drei Kopien vor den drei Funktionsaufrufen aus. Interleaving, wie Sie es erwarten, wäre auch eine gute Wahl. –

+0

Also, wenn die Funktion noch nicht aufgerufen wurde, bedeutet das auch, dass ihr Stack-Frame noch nicht eingerichtet ist. Wo werden diese Objekte gespeichert? – hebbo

+0

Möglicherweise in Registern; 'Gewicht' ist klein genug, um in ein Register zu passen. Möglicherweise wurden die Copy-Konstruktoren inline, und die drei print-Anweisungen wurden von den drei int-Initialisierungen getrennt und in einer anderen Reihenfolge ausgeführt. Wenn Sie genug wissen möchten, um sicher zu wissen, untersuchen Sie die generierte Baugruppe. –

Antwort

0

Ich denke, das ist eine grundlegende Compiler-Optimierung. Da es keine Anforderung gibt, wenn die Parameter einer Funktion aus bereitgestellten Argumenten initialisiert werden sollen, kann ein Compiler die notwendige Optimierung durchführen, indem er sie neu anordnet. Deshalb sehen Sie die Kopierkonstruktoren alle gleichzeitig aufgerufen.

+0

Also, wenn die Funktion noch nicht aufgerufen wurde, bedeutet das auch, dass ihr Stack-Frame noch nicht eingerichtet ist. Wo werden diese Objekte gespeichert? – hebbo

Verwandte Themen