mardi 29 novembre 2022

how does std::vector deal with the call to destructor?

When tring to implement std::vector, I get confused with the implicit call to destructor.

Then element in vector maybe:

  • T
    • a Class Obecjt,
  • T*, shared_ptr<T>
    • a Smart/Simple Pointer to Class Obecjt
  • int
    • built-in type
  • int *
    • pointer to built-in type

When calling resize(),reserve() ,erase()or pop_back(), the destructor might be called.

I wonder how does std::vector deal with the call to destructor.

I found, only when the type is a build-in pointer won't std::vector call the destructor(Of course if it have one).

Does std::vector implement it by distinguishing type and determine whether or not call the destructor?

Below are some experiments about the question:

Example 1, the element is Object.

#include <vector>
#include <iostream>
using namespace std;

struct Tmp {
    ~Tmp() { cerr << "Destructor is called." << endl; }
};

int main (void)
{
    std::vector<Tmp>arr;
    Tmp tmp = Tmp();
    cerr << "Capacity:" << arr.capacity() << endl;//0
    arr.push_back (tmp);
    cerr << "Capacity:" << arr.capacity() << endl;//1
    arr.push_back (tmp);
    cerr << "Capacity:" << arr.capacity() << endl;//2
    cerr << "popback start------------" << std::endl;
    arr.pop_back();
    arr.pop_back();
    cerr << "popback end--------------" << endl;
}

the output is:

Capacity:0
Capacity:1
Destructor is called.
Capacity:2
popback start------------
Destructor is called.
Destructor is called.
popback end--------------
Destructor is called.

Example 2, the element is builtin-in pointer to obecjt:

...
std::vector<Tmp>arr;
Tmp * tmp = new Tmp;
...

The destructor won't be called automatically:

Capacity:0
Capacity:1
Capacity:2
popback start------------
popback end--------------

Example 3, shared_ptr

std::vector<shared_ptr<Tmp>>arr;
auto tmp = make_shared<Tmp>();

... //after being copied, the references count should be 3.
tmp = nullptr; //References count reduced by 1

cerr << "popback start------------" << std::endl;
arr.pop_back();//References count reduced by 1
arr.pop_back();//References count reduced by 1
cerr << "popback end--------------" << endl;

The destructor of shared_ptr will be called. When the references reduced to 0, the destructor of Tmp will be called:

Capacity:0
Capacity:1
Capacity:2
popback start------------
Destructor is called.
popback end--------------

Aucun commentaire:

Enregistrer un commentaire