Как вызываются конструкторы и деструкторы при использовании векторов в c ++ - PullRequest
0 голосов
/ 12 июля 2020

Я пробовал простой код ниже

#include <iostream>
#include <string>
#include <vector>
using namespace std;
class employee
{
    private:
        int emp_id;
    public:
        void getEmpid(){cout<<emp_id<<endl;}
        void setEmpid(){ cin>>emp_id;}
        employee():emp_id(10){cout<<"construct 1 "<<"employee id "<<emp_id<< endl;}
        employee(int empid):emp_id(empid){cout<<"construct 2 "<<"employee id "<<emp_id<<endl;}
        employee(const employee &emp):emp_id(emp.emp_id){cout<<"copy construct 3  "<<"employee id "<<emp_id<<endl;}
        employee(employee&& other) : emp_id(other.emp_id) {cout<<"move construct 4 "<<"employee id "<<emp_id<<endl;}
        ~employee(){cout<<"destructor"<<endl;}
};

int main()
{
    vector<employee>a;
    employee s[8]={1,2,3,4,5}; 

    for(int i=0;i<sizeof(s)/sizeof(s[0]);i++)
        a.push_back(s[i]);
    a.push_back(20);
    a.push_back(30);
    a.push_back(40);
    a.push_back(50);
    a.push_back(60);
    for(int i=0;i<a.size();i++)
        a[i].getEmpid();

    return 0;
}

* Я получил следующий результат. Не очень понятно, как вызываются конструкторы и деструкторы и в каком порядке. может кто-нибудь пролить свет? *

Вывод: построить 2 сотрудника с идентификатором 1 построить 2 сотрудника с идентификатором 2 построить 2 сотрудника с идентификатором 3 построить 2 сотрудника с идентификатором 4 построить 2 сотрудника с идентификатором 5 создать 1 сотрудника с идентификатором 10 создать 1 сотрудника с идентификатором 10 создать 1 сотрудника с идентификатором 10 копировать конструкцию 3 идентификатор сотрудника 1 копировать конструкцию 3 идентификатор сотрудника 2 копировать конструкцию 3 идентификатор сотрудника 1 деструктор копировать конструкцию 3 идентификатор сотрудника 3 копировать конструкцию 3 идентификатор сотрудника 1 копировать конструкцию 3 идентификатор сотрудника 2 деструктор деструктор копировать конструкцию 3 идентификатор сотрудника 4 копировать конструкцию 3 идентификатор сотрудника 5 копировать конструкцию 3 идентификатор сотрудника 1 копировать конструкцию 3 идентификатор сотрудника 2 копировать конструкцию 3 идентификатор сотрудника 3 копировать конструкцию 3 идентификатор сотрудника 4 деструктор деструктор деструктор деструктор копировать конструкцию 3 идентификатор сотрудника 10 копировать конструкцию 3 идентификатор сотрудника 10 копировать конструкцию 3 идентификатор сотрудника 10 построить 2 сотрудника с идентификатором 20 переместить конструкцию 4 идентификатор сотрудника 20 копировать конструкцию 3 идентификатор сотрудника 1 копировать конструкцию 3 идентификатор сотрудника 2 копировать конструкцию 3 идентификатор сотрудника 3 копировать конструкцию 3 идентификатор сотрудника 4 копировать конструкцию 3 идентификатор сотрудника 5 копировать конструкцию 3 идентификатор сотрудника 10 копировать конструкцию 3 идентификатор сотрудника 10 копировать конструкцию 3 идентификатор сотрудника 10 деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор построить 2 сотрудника с идентификатором 30 переместить конструкцию 4 ID сотрудника 30 деструктор построить 2 сотрудника с идентификатором 40 переместить конструкцию 4 сотрудника с идентификатором 40 деструктор построить 2 сотрудника с идентификатором 50 переместить конструкцию 4 идентификатор сотрудника 50 деструктор построить 2 сотрудника с идентификатором 60 переместить конструкцию 4 сотрудника с идентификатором 60 деструктор 1 2 3 4 5 10 10 10 20 30 40 50 60 деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор деструктор

1 Ответ

1 голос
/ 12 июля 2020

Внесение небольших изменений в ваш код сделает вывод легко понятным. В частности, измените деструктор:

   ~employee(){cout<<"destructor " << emp_id <<endl;} // shows emp_id when destructing

И измените свой main, чтобы получить меньший, но похожий результат. Я добавил несколько cout, чтобы разделить вещи и сделать его более понятным при просмотре вывода:

int main()
{
    vector<employee>a;
    
    std::cout << "\ncreating array of employee[3]...\n" << std::endl;
    
    employee s[3]={1,2};
    
    std::cout << "\nstarting loop, copy into vec a\n" << std::endl;

    for(int i=0;i<sizeof(s)/sizeof(s[0]);i++) {
        cout << "Vec size now: " << a.size() << " Capacity: " << a.capacity() << endl;
        a.push_back(s[i]);
    }

    cout << "Outside, Vec size now: " << a.size() << " Capacity: " << a.capacity() << endl;
    
    std::cout << "\ndoing push back outside loop\n" << std::endl;
        
    a.push_back(20);
    a.push_back(30);
    
    std::cout << "\nAll done exiting...\n" << std::endl;

     //removed this, since we are only talking about ctors / dtors
     //reduces noise
    // for(int i=0;i<a.size();i++)
    //     a[i].getEmpid();

    return 0;
}

Результат, который я получил, был следующим, я разделю его и объясню:

Некоторые определения, касающиеся вектора:

  • Емкость : количество элементов, которые могут храниться в выделенной в данный момент памяти
  • Размер : количество элементов в векторе

Код: employee s[3]={1,2};

Вывод:

creating array of employee[3]...

construct 2 employee id 1
construct 2 employee id 2
construct 1 employee id 10

Три конструктора вызываются, 2 employee(int) и 1 по умолчанию. Первые два элемента массива вызывают employee(int). Третий элемент создается по умолчанию.

Код:

    for(int i=0;i<sizeof(s)/sizeof(s[0]);i++) {
        cout << "Vec size now: " << a.size() << " Capacity: " << a.capacity() << endl;
        a.push_back(s[i]);
    }

Вывод:

starting loop, copy into vec a

//iteration 1
Vec size now: 0 Capacity: 0 //vec is zero initially
copy construct 3  employee id 1 //id 1 is copy constructed and pushed back

//iteration 2
Vec size now: 1  Capacity: 1  //vec is now size: 1, with 1 element
//we are doing a push back, but the size needs to grow. Vector reallocates and size becomes 2. The previous memory and the elements in that memory are deallocated/destructed.

copy construct 3  employee id 2 //push back(), copy contruct into vector
copy construct 3  employee id 1 // since we reallocated, the previous memory is gone,
                                //we need to add the previous element as well
destructor 1                    //previous element, id: 1, now being destructed.

//iteration 3
//follows the same logic as in iteration 2. size by the end will be 3 (3 elements). Capacity will be 4. That means we can do one more push back without destroying everything and reallocating.

Vec size now: 2  Capacity: 2
copy construct 3  employee id 10
copy construct 3  employee id 1
copy construct 3  employee id 2
destructor 1
destructor 2

Outside, Vec size now: 3 Capacity: 4                                                                                                    

Код:

    a.push_back(20);
    a.push_back(30);

Вывод:

doing push back outside loop
//remember we have capacity 4

construct 2 employee id 20     //construct id 20
move construct 4 employee id 20 //move into push_back() (because 20 is temporary, rvalue)
destructor 20                   //destroy what we constructed

//capacity: 4, size: 4

construct 2 employee id 30      // construct id 30
move construct 4 employee id 30 //move into push_back()
//uh oh.. capacity was full, deallocations, destructions, reconstructions:
copy construct 3  employee id 1
copy construct 3  employee id 2
copy construct 3  employee id 10
copy construct 3  employee id 20
destructor 1
destructor 2
destructor 10
destructor 20
destructor 30 //destroy our temporary id: 30

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

All done exiting...

destructor 10
destructor 2
destructor 1
destructor 1
destructor 2
destructor 10
destructor 20
destructor 30

Урок: Используйте reserve(), когда можете.

Более того, загляните в vector::clear(), vector::shrink_to_fit , посмотрите что делает. Прочтите документацию для получения дополнительной информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...