Внесение небольших изменений в ваш код сделает вывод легко понятным. В частности, измените деструктор:
~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
, посмотрите что делает. Прочтите документацию для получения дополнительной информации.