Es gibt mindestens zwei "Arten" von Optimierungen in C++.
-
Die erste Art sind spezifische Optimierungen, die ausdrücklich durch die Sprachspezifikation eingeführt werden.
-
Die zweite Art sind all die wilden und unvorhersehbaren Optimierungen, die Compiler unter der "als-ob"-Regel durchführen (d.h. der Compiler kann absolut alles tun, solange das beobachtbare Verhalten des Programms unverändert bleibt).
(Man könnte sagen, dass nur die zweite Art von Optimierungen wahr Optimierungen).
Was Sie hier sehen, ist eine Optimierung der ersten Art. Bei der Durchführung von mehrstufigen Kopiervorgängen hat die Sprachspezifikation den Compilern ausdrücklich erlaubt, temporäre Zwischenkopien zu eliminieren.
Darüber hinaus gehen C++03 und spätere Versionen der Sprachspezifikation noch einen Schritt weiter: Sie erlauben den Compilern ausdrücklich, die "Named Return Value Optimization" (NRVO) durchzuführen, die ein benanntes (nicht temporäres) Objekt tatsächlich eliminiert.
Beide reduzieren die Anzahl der Kopiervorgänge im Programm.
Solche Optimierungen zur Beseitigung von Kopien sind in C++ auch dann zulässig, wenn sie das beobachtbare Verhalten des Programms verändern, d.h. die Optimierungen der ersten Art können manchmal gegen die für die zweite Art geltenden Einschränkungen verstoßen. In Ihrem Fall, obwohl Sie E/A-Operationen in den Kopierkonstruktor eingefügt haben, ist es dem Compiler dennoch erlaubt, die Aufrufe dieses Konstruktors zu eliminieren.
Der Code, den Sie gepostet haben, erfordert keine NRVO. Ein guter C++98-Compiler sollte in der Lage sein, das von Ihnen beobachtete Ergebnis zu erzeugen. Wenn Sie sehen wollen, ob Ihr Compiler in solchen Fällen NRVO ausführt, können Sie Folgendes versuchen
CA foo(){
Ca ca;
return ca;
}