Почему мой деструктор вызывается несколько раз? - PullRequest
0 голосов
/ 09 февраля 2019

Я создал класс и создал вектор этого класса.Я поместил сообщение cerr в деструктор, чтобы увидеть, когда оно вызывается.Я полагал, что один и тот же деструктор вызывается не раз.Это меня озадачивает.

#include <iostream>
#include <vector>

using namespace std;

class temp {
private:
    int _size = 1000;
    int _myBall [1000];
    int _id;
public:
    temp(int id) : _id(id) {}
    ~temp() {
        cerr << "destructor called. ID: " << _id << endl;
    }
};

int main() 
{
    vector<temp> myvec;
    int total_count = 5;
    int count = total_count;
    for(int count = 0;count < total_count; count++) {
        cerr << "count: " << count << endl;
        myvec.push_back(temp(count));
    }

    myvec.clear();
    cerr << "Hello World" << endl;
    system("pause");
    return 0;
}

Вывод на консоль:

count: 0
destructor called. ID: 0
count: 1
destructor called. ID: 0
destructor called. ID: 1
count: 2
destructor called. ID: 0
destructor called. ID: 1
destructor called. ID: 2
count: 3
destructor called. ID: 0
destructor called. ID: 1
destructor called. ID: 2
destructor called. ID: 3
count: 4
destructor called. ID: 0
destructor called. ID: 1
destructor called. ID: 2
destructor called. ID: 3
destructor called. ID: 4
destructor called. ID: 0
destructor called. ID: 1
destructor called. ID: 2
destructor called. ID: 3
destructor called. ID: 4

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Давайте посмотрим на

myvec.push_back(temp(count));

Здесь вы создаете временный temp объект с temp(count).Затем он сохраняется как копия внутри вектора.Затем временный объект уничтожается.

Уничтожение временного объекта является одним из случаев вызова деструктора.

Затем, когда вектор динамически изменяет размеры, он копирует содержимое в новую большую память данных.Объект из меньшей памяти данных будет уничтожен.Что, конечно, приводит к тому, что деструктора называют.И это изменение размера и копирование может происходить несколько раз.

Что касается того, как работает алгоритм изменения размера вектора, это очень зависит от реализации, но общий способ состоит в том, чтобы изменять размер для каждого push_back, пока размер маленький, а затемзарезервируйте все более крупные куски по мере увеличения размера.

Если вы не хотите изменять размеры и копировать, тогда, если вы знаете количество элементов, которые будут сохранены в векторе, вы можете установить определенный размер наначните с и используйте обычный синтаксис индексации массива для присваивания элементам, или вы можете reserve пробел вперед.

0 голосов
/ 09 февраля 2019

Деструктор вызывается из-за копирования, выполняемого каждый раз, когда std::vector изменяет размер.

std::vector перераспределяет заранее определенный объем памяти после его создания (достаточно для хранения некоторого количества temp экземпляров) - это capacity.Каждый раз, когда вызывается push_back, он оценивает, достаточно ли памяти выделено для нового экземпляра.После того, как он заполнен, он фактически перераспределяет другой кусок памяти (достаточно для выделения большего числа temp экземпляров), а затем копирует (или перемещает, если возможно) все существующие экземпляры.Это вызовы деструкторов, которые вы видите записанными в журнал.

Если вы заранее знаете, сколько экземпляров будет необходимо хранить в векторе, вы можете reserve указать это количество.

...