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.
'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. –
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
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. –