8

I am having the problem that my class destructor is called when the class is constructed. Consider the following test program:

#include <iostream>
#include <vector>

using namespace std;

class X
{
public:
    X()  { cout << "X::X()" << endl; };
    ~X() { cout << "X::~X()" << endl; };
};

class Y : public X
{
public:
    Y() : X() { cout << "Y::Y()" << endl; };
    ~Y()      { cout << "Y::~Y()" << endl; };
};

int main() {
    vector<Y> a;
    a.resize(10);
    while(true) ;
    return 0;
}

The output (from before the loop) is

X::X()
Y::Y()
Y::~Y()
X::~X()

I don't understand the behaviour of the above snippet:

  1. Why is only a single element constructed?
  2. Why are the destructors called?
janoliver
  • 7,744
  • 14
  • 60
  • 103
  • 1
    Things would be clearer if you removed the infinite loop, so you could see all the objects getting destroyed, and provided verbose copy constructor and assignment operator, so you can see all elements being constructed/assigned. – juanchopanza Mar 17 '14 at 11:19
  • Hi @juanchopanza, thanks for the comment. Since I wanted to have the destruction occuring before the loop distinguishable from the usual destruction that happens because the scope ends, I introduced the loop. – janoliver Mar 17 '14 at 12:09

1 Answers1

10

The prototype of std::vector::resize() is:

void resize( size_type count, T value = T() );

So it creates a temporary default value to be inserted into the vector (your constructor call), then it is copy-constructed 10 times into the vector (you do not log those), and then the temporary is destroyed (your destructor call).

Note that things have changed for C++11. Now there are two overloads:

void resize( size_type count );
void resize( size_type count, const value_type& value);

So, if you use a proper C++11 compiler you will call the first overload and your values will be value-initialized, that is it will use the default constructor.

rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • Ah, I see. Can I, without much hassle, detect this in my destructor to avoid freeing non-allocated memory? – janoliver Mar 17 '14 at 11:21
  • @Angew: I was typing just that ;-) – rodrigo Mar 17 '14 at 11:22
  • 2
    @janoliver Why should this matter to you? If your class manages memory (or another resource), it *must* follow the [rule of three](http://stackoverflow.com/q/4172722/1782465) and so it should work in the presence of copying just fine (otherwise it's just disaster waiting to happen). – Angew is no longer proud of SO Mar 17 '14 at 11:23
  • @janoliver: Not easily. It seems that you want to use a vector of non-copyable objects, and that is a bad idea. Use a vector of pointers, or something like that. – rodrigo Mar 17 '14 at 11:24
  • @Angew: Okay, thank you for the comment. I'll dig into this "rule of three". – janoliver Mar 17 '14 at 11:24
  • @janoliver Note that in C++11, this generally extends into "rule of five" (move ctor & move assignment op added). But the best is to follow "rule of zero" and delegate resource-management to dedicated RAII classes (such as smart pointers). Then your copy & move operations can be left to the default-generated ones. – Angew is no longer proud of SO Mar 17 '14 at 11:26