C++ 当使用向量创建对象时,如何调用析构函数
对于如何在通过向量构造的对象上调用析构函数,我有点困惑,但在使用指针创建对象时只调用了一次C++ 当使用向量创建对象时,如何调用析构函数,c++,vector,destructor,C++,Vector,Destructor,对于如何在通过向量构造的对象上调用析构函数,我有点困惑,但在使用指针创建对象时只调用了一次 #include <iostream> #include <vector> #include <string> class Student { std::string first; std::string last; int age; public: Student(); Student(std::string f, std:
#include <iostream>
#include <vector>
#include <string>
class Student
{
std::string first;
std::string last;
int age;
public:
Student();
Student(std::string f, std::string l, int a) : first(f), last(l), age(a)
{
};
~Student()
{
cout << "Destructor\n";
}
};
int main()
{
std::vector<Student> Univ;
Univ.push_back(Student("fn1", "ln1", 1));
Univ.push_back(Student("fn2", "ln2", 2));
Univ.push_back(Student("fn3", "ln3", 3));
return 0;
}
我只接到了一个叫析构函数的电话
这是为什么?您正在创建一个临时的
学生
,将其传递到push_back
,并将其复制到向量中。结果是,您使用每个Student
实例的两个副本,并调用每个实例的析构函数。此外,当您添加更多的Student
s并调整向量大小时,现有内容将复制到新分配的内存中,从而导致更多的析构函数调用
如果您有可用的C++11功能,您可能需要查看。当您执行
推回操作时,向量没有足够的内存来存储它必须调整大小的新元素,每次调整向量大小时,它都会调用旧元素的析构函数。试试这个:
std::vector<Student> Univ(3);
Univ.push_back(Student("fn1", "ln1", 1));
Univ.push_back(Student("fn2", "ln2", 2));
Univ.push_back(Student("fn3", "ln3", 3));
std::矢量大学(3);
大学推回(学生(“fn1”,“ln1”,1));
大学推回(学生(“fn2”,“ln2”,2));
大学推回(学生(“fn3”,“ln3”,3));
除此之外,您正在创建要传递到push_back
的临时对象,这就是额外析构函数调用的原因
当我后退一次时,我接到两个对析构函数的调用。2推回,
我接到5个到析构函数的电话。3次推回,我接到9个电话
析构函数
在C++11之前,将对象推回到std::vector
系统时,将对象复制到容器中。所以,若你们做一次推回,系统创建了两个对象,那个么系统必须调用2次析构函数来清理
从C++11开始,如果为调用定义移动复制构造函数,std::vector将使用移动语义代替复制构造函数,并将对象移动到vector,而不是复制对象。所以系统将只生成一个析构函数调用。
下面的链接将给你更好的想法可能向量空间不足,在其他地方获得了更多空间,并将学生复制或移动到新空间。然后在旧空间为学生调用了析构函数。@nwp在一个较大的程序中,有大量的后推,这会是一个缺点吗?这是无法避免的,除非你事先知道大小。但是调整大小的情况很少发生,所以不要太担心。如果您能猜出大小,可以使用vector.reserve(大小)。列表没有这个问题,但它们还有其他更糟糕的问题。在C++11中,使用移动语义可以大大减少开销。如果复制/移动对象非常昂贵,可以使用指向对象的指针。这将最小化调整大小的成本,但会增加访问成本,使事情变得不那么方便。请注意,如果他只是删除他的析构函数,他将免费获得移动语义。
std::vector<Student> Univ(3);
Univ.push_back(Student("fn1", "ln1", 1));
Univ.push_back(Student("fn2", "ln2", 2));
Univ.push_back(Student("fn3", "ln3", 3));