Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the destructor called when initializing and resizing a vector of objects?

Tags:

c++

vector

Something occurred in my program, and I can't find if it's supposed to happen or not. And if it is, I don't see why..

Here's the code :

#include <iostream>
#include <vector>

using namespace std;

class A{
  public:
    A();
    ~A();
};

A::A(){
  cout << "creating" << endl;
}

A::~A(){
  cout << "deleting" << endl;
}

int main(void){
  vector<vector<A > > vec;

  vec.resize(5);
  for(int i = 0; i < 5; ++i){
    vec[i].resize(5);
  }

  cout << "END" << endl;

  return 0;
}

And here's the output :

creating
deleting
creating
deleting
creating
deleting
creating
deleting
creating
deleting
END
deleting
deleting
[..more deleting here]

I understand why the destructor is called after the "END" message, but before, I don't. I thought that when the vector resize, the constructor of the class is called, but why the destructor?

like image 961
user1729422 Avatar asked Jan 16 '13 18:01

user1729422


People also ask

Is the destructor always called?

No. You never need to explicitly call a destructor (except with placement new ). A derived class's destructor (whether or not you explicitly define one) automagically invokes the destructors for base class subobjects. Base classes are destructed after member objects.

What happens when vector is resized?

vector::resize() The function alters the container's content in actual by inserting or deleting the elements from it. It happens so, If the given value of n is less than the size at present then extra elements are demolished.

Does vector have destructor?

One way of deleting a vector is to use the destructor of the vector. In this case, all the elements are deleted, but the name of the vector is not deleted.

How many times destructor is called?

The destructor is being called three times, for a , lol and b . In your case, a and b are instantiated using the default constructor .


1 Answers

In C++03 vector<A>::resize() has a default parameter, with default value A(). It's this temporary that's destroyed. The elements of the vectors are copy constructed from it.

This is "fixed" in C++11, where there are two overloads of resize. One has a single parameter, and value-initializes any additional elements. The other has two parameters, and copy-initializes each additional element from the value supplied. In C++11 this program has this behavior:

creating
creating
creating
<repeated for a total of 25 "creating"s>
creating
creating
creating
END
deleting
deleting
deleting
<repeated for a total of 25 "deleting"s>
deleting
deleting
deleting

In C++03, if an instance of A is so shockingly expensive to construct that it's worth minimizing the number, then you could shave it from 5 no-args- + 25 copy-constructions down to 1 no-arg- and 25 copy-constructions with something like this:

A default_value;
for (int i = 0; i < 5; ++i) {
   // same end result as vec[i].resize(5)
   if (vec[i].size() >= 5) {
       vec[i].erase(vec.begin() + 5, vec.end());
   } else while(vec[i].size() < 5) {
       vec[i].push_back(default_value);
   }
}

You can probably write it slightly differently, and obviously for your example code you don't need the "if" case. But I don't get many opportunities to say "else while", so I'm taking it.

like image 70
Steve Jessop Avatar answered Oct 08 '22 21:10

Steve Jessop