注意:如下源码的执行和实现分析仅适用Linux平台,其他平台暂未测试。
一直以为一个class的vector,当进行resize操作的时候,会调用n次构造函数。但其实不是,无论resize(n)中的n有多大或是多小,在进行resize操作的时候仅仅只会调用一次构造函数。
比如下面的例子:
源码:
/*
*vec.cpp
*/
#include <vector>
#include <iostream>
using namespace std;
class A
{
public:
A(){cout<<"create."<<endl;}
~A(){cout<<"destory."<<endl;}
};
int main()
{
vector<A> vecA;
cout<<"resize(10)"<<endl;
vecA.resize(10);
cout<<"resize(5)"<<endl;
vecA.resize(5);
cout<<"end."<<endl;
return 0;
}
输出:
resize(10)
create.
destory.
resize(5)
create.
destory.
destory.
destory.
destory.
destory.
destory.
end.
destory.
destory.
destory.
destory.
destory.
分析原因:
resize的源码如下:
/**
* @brief Resizes the %vector to the specified number of elements.
* @param new_size Number of elements the %vector should contain.
* @param x Data with which new elements should be populated.
*
* This function will %resize the %vector to the specified
* number of elements. If the number is smaller than the
* %vector's current size the %vector is truncated, otherwise
* the %vector is extended and new elements are populated with
* given data.
*/
void
resize(size_type __new_size, value_type __x = value_type())
{
if (__new_size > size())
insert(end(), __new_size - size(), __x);
else if (__new_size < size())
_M_erase_at_end(this->_M_impl._M_start + __new_size);
}
我们发现,在resize开始的时候就会构造一个临时的class A的变量,不妨设为tmpA。
如果__new_size > size(),就会进行insert的操作,其实insert的实现是这样的(伪代码):
bool insert(iterator _pos, int _size, A tmpA)
{
//申请空间
A *listA = (A *)malloc(sizeof(A)*_size);
//赋值
for(int i=0; i<_size; i++)
{
memcpy(listA+i, &tmpA, sizeof(A));
}
//将listA中的各个元素链接到vector中
...
}
如果__new_size < size(),就会进行erase操作,直接调用相应的析构函数就ok啦,
最后同样不要忘了tmpA的析构。