在c++中使用向量时,如何调用构造函数和析构函数



我在下面尝试一个简单的代码

#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员工id 1
构建2员工id 2
构筑2员工id 3
构2员工id 4
建构1员工id 10
架构1员工id 10
复制构造3员工id 1
复制构3员工id 2
副本构造3员工id 1
析构函数
副本构造3员工id 3
复制构造3员工id 1
副本构造3员工id 2
析构函数
销毁函数
复制构造3人员id 4
拷贝构造3员工id5
copy构造3员工ID1
copy构造3人员id2
copy构造3员工Id3
copy构造3员工id=4
析构函数/>析构函数/>复制构造3员工id 10
复制构造3雇员id 10
复制构造3职员id 10
析构函数
析构函数
析构因子
解构函数
<析构函数>br员工id 40
析构函数
构造2员工id 50
移动构造4员工id 50
析构函数
构造2员工id 60
移构造4员工id 60
析构函数
1
2
3
4
5
10
10
20
30
40
50
60
析构函数
解构函数
br/>析构函数/>析构函数

对代码进行一点修改将使输出易于理解。具体来说,更改析构函数:

~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 an" << 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 loopn" << 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,看看它有什么作用。阅读文档了解更多信息。

  • 关于矢量增长的SO链接:关于矢量增长
  • cpprreference中的std::vector文档

最新更新