c ++ destructor destruyendo más objetos que el constructor creado

I am trying to get familiar with constructors and destructors in C++. The below program simply creates a complex number, prints it on the stdio and exits. I have created 3 objects (1. using default constructor, 2. using explicit constructor and third using the copy constructor. Before exiting, it destructed 4 objects. Why my program below is destructing more objects than the constructor ever created?

#include <iostream>

using namespace std;
class complex
{
private: float a; float b;
public: float real(){return a;};
    float imag(){return b;};

    complex(){a=0.0; b=0.0;cout << "complex no. created."<<endl;};
    complex(float x, float y){a=x; b=y;};
    ~complex(){cout << "complex no. with real part " << this->real() << " destroyed" << endl;};

    void display(){cout << a << '+' << b << 'i';}
    friend ostream& operator<< (ostream & sout, complex c)
    {
        sout << c.a << '+' << c.b << 'i' << "\n";
        return sout;
    }
};
main()
{
    complex c1;
    complex c2(1.0,1.0);

    c1.display();
    cout << endl;
    c2.display();
    cout << endl;
    cout << c2.imag() << endl;
    complex c3 = c2; // this uses the default 'copy constructor'
    c3.display();
    cout << endl;
    cout << c2;
}

La salida que obtengo es:

complex no. created.
0+0i
1+1i
1
1+1i
1+1i
complex no. with real part 1 destroyed
complex no. with real part 1 destroyed
complex no. with real part 1 destroyed
complex no. with real part 0 destroyed

Just for the sake of completion, I have tried this on CC as well as g++ compilers. And both of them behave same.

preguntado el 23 de septiembre de 13 a las 03:09

3 Respuestas

friend ostream& operator<< (ostream & sout, complex c)

is passing complex by value, so another complex is being created.

change the function parameters to

friend ostream& operator<< (ostream & sout, const complex& c)

This will pass complex by reference (saving a copy being created and destroyed).

The const qualifier means that your function will not modify the contents of c. Without a const qualifier on your function, it would not accept constant complex objects, so the following code would cause an error (which is not what you want).

const complex a_constant_complex(1.0,1.0);
cout << a_constant_complex << endl;

Other notes about your code

Also if at all possible get out of the habit of using 'using namespace std;'. Pulling the whole of the std namespace into your global namespace is not a good thing.

And the trailing '<< "\n"' in the operator<< shouldn't be there either. The purpose of operator<< is to send yourself to the stream, if the caller wants a newline after it, they'll add a << endl like I did in my constant example.

Respondido el 23 de Septiembre de 13 a las 03:09

Your class has another constructor - an implicitly defined copy constructor. It doesn't print anything, but objects get constructed with it nevertheless.

Define your own copy constructor, print something in it - then you'll see constructors and destructors line up.

Su operator<< toma complex by value, so a temporary is created whenever you call it. That's where the "extra" constructor/destructor pair comes from.

Respondido el 23 de Septiembre de 13 a las 03:09

+1 and while at it, output messaging in the alternate constructor as well. May as well. - QuiénesCraig

Cambie a friend ostream& operator<< (ostream & sout, const complex& c) and watch the mystery go away. - David Schwartz

you should mention the rule of three (or five in C++11) - Yakk - Adam Nevraumont

the rule of 3 doesn't really apply here. He doesn't have a copy constructor, or a copy assignment, and once he has finished debugging he won't have a destructor. So he won't have any of the 3, so there is no reason to have all 3. - Cuerdas

And as only member functions are floats, the compiler is perfectly capable of generating all 3/5. In fact it would be wrong to define them on such a simple class! - Cuerdas

Add the copy constructor, insert breakpoints and observe :)

complex(complex &copycomplex)
{
    cout << "hello from the copy constructor." << endl;
    *this = copycomplex;
};

Respondido el 23 de Septiembre de 13 a las 10:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.