我创建了一个类,并创建了这个类的载体。我已经把cerr
消息中的析构函数时看到它被称为。我想,同样的析构函数获取调用一次以上。这使我感到困惑。
#include <iostream>
#include <vector>
using namespace std;
class temp {
private:
int _size = 1000;
int _myBall [1000];
int _id;
public:
temp(int id) : _id(id) {}
~temp() {
cerr << "destructor called. ID: " << _id << endl;
}
};
int main()
{
vector<temp> myvec;
int total_count = 5;
int count = total_count;
for(int count = 0;count < total_count; count++) {
cerr << "count: " << count << endl;
myvec.push_back(temp(count));
}
myvec.clear();
cerr << "Hello World" << endl;
system("pause");
return 0;
}
控制台输出:
count: 0
destructor called. ID: 0
count: 1
destructor called. ID: 0
destructor called. ID: 1
count: 2
destructor called. ID: 0
destructor called. ID: 1
destructor called. ID: 2
count: 3
destructor called. ID: 0
destructor called. ID: 1
destructor called. ID: 2
destructor called. ID: 3
count: 4
destructor called. ID: 0
destructor called. ID: 1
destructor called. ID: 2
destructor called. ID: 3
destructor called. ID: 4
destructor called. ID: 0
destructor called. ID: 1
destructor called. ID: 2
destructor called. ID: 3
destructor called. ID: 4
析构函数,由于完成每次std::vector
调整大小时拷贝调用。
std::vector
一旦它的构造重新分配的存储器中的预先确定的量(足以容纳temp
实例的一些数) - 这是capacity
。每次push_back
被调用时,评估是否仍然有足够的内存分配,以适应新的实例。一旦被填充,它实际上重新分配存储另一块(足以分配temp
实例的更大的数字),然后副本(或移动时,如果可能的话)中的所有现有实例。这些都是你看到记录的析构函数调用。
如果你知道前手有多少实例向量的人都需要持有,您可以将其reserve
这一数额。
让我们看一下
myvec.push_back(temp(count));
在这里,您创建temp
临时temp(count)
对象。这然后被存储为矢量内部副本。然后临时对象被销毁。
临时对象的破坏,析构函数的一种情况下被调用。
然后为矢量动态调整大小本身,它的内容复制到新的更大的数据存储器。从更小的数据存储器中的对象将被破坏。这当然会导致析构函数被调用。而这种调整大小和复制会发生多次。
作为载体的调整算法是如何工作的这是非常具体的实现,但是一个常用的方法是调整为每push_back
虽然尺寸小,然后保留越来越大的块的大小增加。
如果你不想要这个调整大小和复制,那么只要你知道的元素个数被存储在矢量您可以设置特定的大小开始和正常使用数组索引语法指定的元素,或你可以reserve
空间的前期。