Copy-Constructor und Destructor (2)



  • /* Wer kann folgendes Verhalten erklären:

    Für die Klasse Bruch habe ich den operator * überladen.
    Die Methode returniert ein Objekt per Value. Also wird
    der Copy-C'tor aufgerufen.

    Warum wird der Copy-C'tor bei Variante 1 nicht aufgerufen,
    wenn ein D'tor existiert ? 😋
    */

    #include <iostream>
    
    using namespace std;
    
    class Bruch
    {
    	private:
    		int zaehler;
    		int nenner;
    	public:
    		Bruch(int=0,int=1); 
    		Bruch(const Bruch &);
    		~Bruch();
    		Bruch operator *( Bruch & );
    		friend ostream & operator << ( ostream &, const Bruch &);
    };
    
    Bruch::Bruch(int z, int n)
    :zaehler(z),nenner(n)	         
    {}
    
    Bruch::Bruch(const Bruch &b)
    : zaehler(b.zaehler), nenner(b.nenner)				   
    { 
    	cout << "Copy-C'tor" << endl; 
    }
    
    Bruch::~Bruch(void) { /* hier soll irgendwas passieren */ }
    
    Bruch Bruch::operator *( Bruch &b )
    {   
    	// Variante 1
    	// return Bruch( zaehler * b.zaehler, nenner *  b.nenner );
    
    	// Variante 2
    	Bruch tmp(zaehler * b.zaehler, nenner *  b.nenner);
    	return tmp;
    }
    
    namespace std
    {
    	ostream & operator << ( ostream &o, const Bruch &b)
    	{
    		o << (double)b.zaehler / b.nenner;
    		return o;
    	}
    };
    
    int main(void)
    {
    	Bruch b1;		Bruch b2(1,2);	 Bruch b3(3,4);  
    
    	b1 = b2 * b3;    
    
    	cout << b1 << endl;
    
    	return 0;
    }
    

    /* Ausgabe bei Variante 1 mit D'tor
    0.375
    */

    /* Ausgabe bei Variante 1 ohne D'tor
    Copy-C'tor
    0.375
    */

    /* Ausgabe bei Variante 2 mit D'tor
    Copy-C'tor
    0.375
    */

    /* Ausgabe bei Variante 2 ohne D'tor
    Copy-C'tor
    0.375
    */



  • Was hast du für einen Compiler?
    Der dtor tut hier nichts zur Sache, darum habe ich es getestet und es hat mir bei Variante 1 in beiden Fällen lediglich 0.375 ausgegeben. Und bei Variante 2 mit dem Copy-C'tor. Also so, wie es sein muss. dtor hat nichts zu melden.



  • Ich meine mal gehört zu haben, dass da der Compiler ein wenig rum-optimieren darf. Return-Value-Optimization nennt sich das afaik, der Copy-Ctor-Aufruf fällt dabei weg um redundanten Code zu sparen (weil ja normalerweise das Objekt erzeugt und dann kopiert wird -> Kopie eigentlich unnötig).
    Und ich stimme drakon zu, der Destruktor dürfte da eigentlich nicht viel beeinflussen, aber evtl optimiert der Compiler dann halt anders.



  • Badestrand schrieb:

    Ich meine mal gehört zu haben, dass da der Compiler ein wenig rum-optimieren darf. Return-Value-Optimization nennt sich das afaik, der Copy-Ctor-Aufruf fällt dabei weg um redundanten Code zu sparen (weil ja normalerweise das Objekt erzeugt und dann kopiert wird -> Kopie eigentlich unnötig).
    Und ich stimme drakon zu, der Destruktor dürfte da eigentlich nicht viel beeinflussen, aber evtl optimiert der Compiler dann halt anders.

    Das wäre ja ev. der Fall, wenn sich seine Varianten unterscheiden. Aber das scheint ja nicht das Problem zu sein (bei ihm).
    Also im Optimalfall würde er ihn ja wegoptimieren, da er ja eh leer ist, inwiefern sollte den das einen Einfluss auf die Konstruktion einen Einfluss haben? (Also bei mir hat er das nicht. VC++ 08)



  • Naja, bei Variante 2 wird ja die tmp-Variable benutzt, vielleicht traut sich der Compiler dann nicht ganz, zu kompilieren.
    Und das mit dem Dtor versteh ich wie gesagt auch nicht.. Andere Compiler andere Sitten, wie auch immer 🙂


  • Mod

    Welcher Compiler, welche Optimierungseinstellungen? Grundsätzlich stellt die Eliminierung der Kopien bzw. der Verzicht auf eine solche Eliminierung konformes Verhalten in allen 4 Fällen dar. Alles Weitere ist ein reines QoI-Problem.
    Genaugenommen hat der Code ja sowieso undefiniertes Verhalten 😉



  • QoI?


  • Mod

    quality of implementation



  • Also funktionieren tut er auf alle Fälle schon mal nicht, wegen dem Zugriff auf private Member, aber in wiefern hat er undefiniertes Verhalten? Wegen der Optimierung?


  • Mod

    drakon schrieb:

    Also funktionieren tut er auf alle Fälle schon mal nicht, wegen dem Zugriff auf private Member, aber in wiefern hat er undefiniertes Verhalten?

    Das auch noch. Zudem ist der Aufruf des Operators mehrdeutig. Undefiniert ist es außerdem, weil eine Deklaration im Namensraum std erfolgt, die keine Templatespezialiserung darstellt.


Anmelden zum Antworten