c++中vector的内部工作

Internal working of a vector in C++?

本文关键字:内部 工作 vector c++      更新时间:2023-10-16

我正在用c++做练习,但是我得到了意想不到的输出,我希望有人能解释一下。这个练习要求我创建一个名为rock的类,它有一个默认构造函数,一个复制构造函数和一个析构函数,它们都宣布自己为cout。

在main方法中,我将尝试按值将该类的成员添加到vector中:

vector<Rock> byValue;
Rock r1, r2, r3;
byValue.push_back(r1);
byValue.push_back(r2);
byValue.push_back(r3);
cout << "byValue populatednn";
我期望的输出(并在练习解决方案中显示)是:
Rock()
Rock()
Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
byValue populated
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()

但是我得到的输出是:

Rock()
Rock()
Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
~Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
~Rock()
~Rock()
byValue populated
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()

谁能解释一下为什么似乎有对复制构造函数和析构函数的额外调用?

当vector被调整大小时,元素必须移动到它们的新位置。

正常

如果你调用

byValue.reserve(10);

在调用push_back之前,多余的副本应该消失。

vector连续存储其元素。为了避免每次插入元素时总是重新分配内存,它确实分配了一堆内存。这就是为什么vector有两个关于其"大小"的方法:size()表示存储的元素数量,capacity()表示分配的内存量。

通常(但这取决于STL实现),它通过将其先前容量增加一倍来增长。当它分配更多内存时,由于数据必须连续存储(与list相比),它必须移动其内部数据;STL复制数据,这就是为什么你有这么多调用构造函数/析构函数的原因。

如果你知道vector容器中要存储多少元素,你可以使用reserve来表示首先应该分配多少内存。

std::vector具有有限的内存来存储元素。您可以使用capacity查询多少。您还可以使用reserve方法告诉向量获取额外的内存。

当你将一个元素压入vector容器,而它的容量为零(它已经用完了所有额外的内存),它会分配一个新的更大的数组,并从原来的数组中复制元素。这就是所有额外副本的来源。

看看你的输出,看起来向量必须增长两次。如果将代码改为在压入任何对象之前调用reserve,则vector对象将永远不需要增长,也不会有额外的拷贝。

下面是一个详细的代码片段,展示了所有这些是如何结合在一起的: