Reputation: 3691
I have taken a look at this presentation, and at slide 379, it shows the following code (with a few minor changes):
#include <iostream>
using namespace std;
struct A
{
A() { cout << "A()" << endl; }
A(int v) { cout << "A(int)" << endl; }
~A() { cout << "~A()" << endl; }
};
struct X
{
X(int v) { a = v; }
X(long v) : a(v) {}
A a;
};
int main()
{
cout << "bad style:" << endl;
{ X slow(int(2)); }
cout << "good style:" << endl;
{ X fast(long(2)); }
}
the output is:
bad style:
A()
A(int)
~A()
~A()
good style:
A(int)
~A()
(this code was run on my machine, compiled with g++)
Now, I understood why the constructor will be called twice in the bad style, but why will the destructor do so?
Upvotes: 1
Views: 191
Reputation: 5369
You fallen a victim of "implicit typecast". Try to add "explicit" to your constructors and would see what's wrong in your code (it will stop compiling at the place of the former implicit conversion):
struct A
{
explicit A() { cout << "A()" << endl; }
explicit A(int v) { cout << "A(int)" << endl; }
~A() { cout << "~A()" << endl; }
};
Here is an explanation: http://en.cppreference.com/w/cpp/language/implicit_cast
Upvotes: 1
Reputation: 4143
Intro
There is an additional thing to consider, when executing constructors & destructors in C++.
Are you declaring a static allocated object or a dynamic allocated object ?
Static Allocation
#include <iostream>
using namespace std;
class A {
public:
// constructors
A() { cout << "A()" << endl; }
A(int v) { cout << "A(int)" << endl; }
// destructors
~A() { cout << "~A()" << endl; }
};
class X {
public:
// constructors
X(int v) { a = v; }
X(long v) : a(v) {}
// variables
A a;
};
int main()
{
cout << "bad style:" << endl;
X slow(int(2));
cout << "good style:" << endl;
X fast(long(2));
}
Dynamic Allocation
#include <iostream>
using namespace std;
class A {
public:
// constructors
A() { cout << "A()" << endl; }
A(int v) { cout << "A(int)" << endl; }
// destructors
~A() { cout << "~A()" << endl; }
};
class X {
public:
// constructors
X(int v) { a = new(v); }
X(long v) : { a = new(); *a = v; }
// destructors
~X() { delete a; }
// variables
A* a;
};
int main()
{
cout << "bad style:" << endl;
X slow = new X(int(2));
cout << "good style:" << endl;
X fast = new (long(2));
// do something else with "X"
delete slow();
delete fast();
}
Summary
Static allocated variables call destructors automatically, while dynamic allocated variables that use pointers, you need to explicitly call the destructor.
** Extra**
If you have previously use another Object Oriented language, or have to switch from C++ to another, this is important to consider, because maybe handle different.
Upvotes: 0
Reputation: 17657
The logic is
Instantiate a Class ... +1 [Constuctor]
Desinstantiate a Class ... -1 [Destructor]
A destructor is called for a class object when that object passes out of scope or is explicitly deleted.
So you can expect that The Destructors of the classes will be called an equal number of times these Classes were created.
Upvotes: 1
Reputation: 55425
X(int v) { a = v; }
// ^^^^^
The underlined line is an assignment. There's no operator=
that takes an int
(v
), but there's an implicit conversion from int
to A
. So, a temporary object of type A
is constructed and passed to assignment operator that the compiler generated for you. It gets destructed later (after the full expression it was created in ends) and there's your second destructor you didn't expect.
Upvotes: 8