问题描述
class Name
{
string _name;
public:
Name(const string& name) : _name(name) { cout << "ctor of " << _name << endl; }
~Name(){ cout << "dtor of " << _name << endl; }
};
int main() {
vector<Name> list;
cout << "------------------START push_back" << endl;
list.push_back(Name(string("A")));
cout << "------------------push_back(A) performed..." << endl;
list.push_back(Name(string("B")));
cout << "------------------push_back(B) performed..." << endl;
list.push_back(Name(string("C")));
cout << "------------------push_back(C) performed..." << endl;
cout << "------------------END push_back" << endl;
return 0;
}
我可以理解 push_back 使用了一个额外的临时对象,这就是为什么推荐 emplace_back 以获得更好的性能。有人可以用 (???) 解释下面输出中显示的额外析构函数调用吗。
------------------START push_back
ctor of A
dtor of A
------------------push_back(A) performed...
ctor of B
dtor of A(???)
dtor of B
------------------push_back(B) performed...
ctor of C
dtor of A(???)
dtor of B(???)
dtor of C
------------------push_back(C) performed...
------------------END push_back
dtor of A
dtor of B
dtor of C
------------------START emplace_back
ctor of A
------------------emplace_back(A) performed...
ctor of B
------------------emplace_back(B) performed...
ctor of C
------------------emplace_back(C) performed...
------------------END emplace_back()
dtor of A
dtor of B
dtor of C
解决方法
有人可以用 (???) 解释下面输出中显示的额外析构函数调用吗。
内存分配的大小不能改变。数组的大小相应地不能改变,因为分配给数组的内存不能改变。
向量的元素存储在分配的单个内存块中,形成一个数组。如果内存块不能改变大小,那么如何向向量添加元素?好吧,我们能做的就是分配更大的内存块,然后将元素从小块复制(移动)到大块,然后销毁旧块中的旧元素,最后释放旧块。这就是当您添加的元素超出其为其元素分配的内存块(称为容量)时,向量会执行的操作。
有人可以用 (???) 解释下面输出中显示的额外析构函数调用吗。
这些是向量重新分配时旧内存中被破坏的元素。
如果您想知道为什么在新内存中构造对象没有输出,那是因为您的类的移动构造函数没有产生输出。
如果您想知道为什么每个添加元素后都没有额外的销毁,那是因为 vector 在增长时不仅仅为单个元素分配内存。相反,它将容量乘以某个因子(通常实现使用 2 或 1.5 的因子)。当最初不知道最终元素数量时,这会为插入大量元素带来更好的渐近复杂度。
,std::vector 是一个动态数组。
每次没有足够的内存分配来存储元素时,std::vector 会尝试重新分配更大的内存块来存储更多元素。之后,它需要将您的元素复制(移动)到其他块,隐式调用先前元素的 dtor。
要了解正在发生的事情,请尝试扩展您的课程:
class Name
{
string _name;
public:
Name(const string& name) : _name(name) { cout << "ctor of " << _name << endl; }
Name(const Name& other) : _name(other._name) { cout << "copy ctor for " << _name << endl; }
~Name(){ cout << "dtor of " << _name << endl; }
};
现在重新运行你的程序,看看有多少复制构造函数被调用。
现在试着打电话
vector<Name> list;
list.reserve(3);
/* push_backs */
并享受:)