【问题标题】:How does the constructors and destructors are called when using vectors in c++c++中使用vector时如何调用构造函数和析构函数
【发布时间】:2020-11-01 15:11:42
【问题描述】:

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

#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
构造 2 个员工 id 5
构造 1 个员工 id 10
构造 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 员工 ID 5
复制构造 3 员工 ID 1
复制构造 3 员工 ID 2
复制构造 3 员工 ID 3
复制构造 3 员工 ID 4
析构函数
析构函数
析构函数
析构函数
复制构造 3 员工 ID 10
复制构造 3 员工 ID 10
复制构造 3 员工 ID 10
构造 2 个员工 id 20
移动构造 4 员工 ID 20
复制构造 3 员工 ID 1
复制构造 3 员工 ID 2
复制构造 3 员工 ID 3
复制构造 3 员工 ID 4
复制构造 3 员工 ID 5
复制构造 3 员工 ID 10
复制构造 3 员工 ID 10
复制构造 3 员工 ID 10
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
构造 2 个员工 id 30
移动构造 4 员工 ID 30
析构函数
构造 2 个员工 id 40
移动构造 4 员工 ID 40
析构函数
构造 2 个员工 ID 50
移动构造 4 员工 ID 50
析构函数
构造 2 个员工 id 60
移动构造 4 员工 ID 60
析构函数
1
2
3
4
5
10
10
10
20
30
40
50
60
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数
析构函数

【问题讨论】:

  • 欢迎来到 StackOverflow!如果您在每个函数中打印出员工 ID,也许会有助于解释发生了什么。
  • 不是很清楚如何调用构造函数和析构函数以及调用顺序 -- 你应该减少你的main 程序,以便得到一个更易于管理的例子。 main 中发生的事情太多了。比如与vectoremployee s[8]={1,2,3,4,5};无关的第一行生成输出。
  • 你为什么不自己尝试一下呢?使用调试器,在涉及类对象的每个语句上设置断点,查看输出屏幕,查看变量。提出你的理论,如果你错了,我们很乐意纠正你。
  • 肯定试一试,容量满时不确定分配/解除分配,感谢Waqar的回答

标签: c++ vector constructor destructor


【解决方案1】:

对您的代码稍作修改将使输出易于理解。具体来说,改变析构函数:

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

并更改您的 main 以提供更小但相似的输出。我添加了几个couts 来分隔事物,以便在查看输出时更容易理解:

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,看看它的作用。阅读文档以获取更多信息。

【讨论】:

  • 非常感谢@Waqar,当容量已满时不确定分配/解除分配。
猜你喜欢
  • 2021-07-28
  • 1970-01-01
  • 2021-07-19
  • 2013-04-17
  • 2011-04-16
  • 1970-01-01
  • 2011-04-03
  • 2010-12-16
  • 2017-02-08
相关资源
最近更新 更多