什么是C ++中真正空的std :: vector?

时间:2010-04-29 16:11:37

标签: c++ stl vector

我在A类中有两个包含其他类对象B和C的向量。我确切地知道这些向量应该保持多少元素。在A类构造函数的初始化列表中,我将这些向量初始化为它们的最大大小(常量)。

如果我理解正确,我现在有一个B类对象的向量,它们已经使用它们的默认构造函数进行了初始化。对?当我编写这段代码时,我认为这是处理事情的唯一方法。但是,我已经了解了std::vector.reserve(),我想要实现不同的东西。

我想为这些向量分配内存以尽可能大,因为添加它们是由用户输入控制的,所以我不想频繁地进行调整。但是,我每秒迭代这个向量很多次,而且我目前只处理我标记为“活动”的对象。必须在每次迭代时检查B / C类的布尔成员是愚蠢的。我不希望这些对象在我的迭代器中存在,以便在我浏览此列表时看到它。

是提前保留最大空间并使用push_back向向量添加新对象的解决方案吗?

3 个答案:

答案 0 :(得分:12)

vector有容量且有大小。容量是已分配内存的元素数。 Size是实际在向量中的元素数。当vector的大小为0时,size()为空。因此,empty()返回0,true返回vector。这没有说明vector在那时的容量(这将取决于capacity()自创建以来已经完成的插入和擦除次数等事情。 vector将告诉您当前容量 - 这是vector在重新分配其内部存储空间以便保留更多内容之前可以容纳的元素数量。

因此,当您构建vector时,它具有一定的大小和一定的容量。默认构造的vector将具有零大小和实现定义的容量。您可以自由地将元素插入vector而无需担心max_size()是否足够大 - 最多max_size() - vectorvector的最大容量/大小可以拥有该系统(通常足够大,不用担心)。每次将项目插入vector时,如果它具有足够的容量,则不会将任何内存分配分配给vector。但是,如果插入该元素将超过vector的容量,那么vector的内存将在内部重新分配,以便它具有足够的容量来容纳新元素以及实现 - 定义的新元素数量(通常,vector的容量可能会加倍)并且该元素将插入到向量中。发生这种情况时,您无需担心增加vector的容量。它发生在constant amortized time,因此您通常不必担心它是性能问题。

如果您确实发现您经常添加reserve()以发生许多重新分配,并且这是一个性能问题,那么您可以调用vector,这会将容量设置为至少给定的价值。通常情况下,当您非常了解vector可能容纳的元素数量时,您就会这样做。但是,除非你知道它会遇到性能问题,否则它可能是一个坏主意。这只会使你的代码复杂化。 constant amortized time通常足以避免性能问题。

如前所述,您还可以使用给定数量的默认构造元素构造vector,但除非您真的需要这些元素,否则这将是一个坏主意。 reserve()应该是这样的,这样你就不必担心在向它插入元素时重新分配容器(就像你必须使用数组一样),并且为此目的使用默认构造元素分配内存正在打败那个。如果您真的想这样做,请使用reserve()。但同样,除非你确定它会提高性能,否则不要打扰vector。正如在另一个答案中指出的那样,如果您根据用户输入将元素插入vector,那么I / O的时间成本将远远超过重新分配内存的时间成本。 capacity() // Returns the number of elements that the vector can hold reserve() // Sets the minimum capacity of the vector. 在那些相对罕见的情况下,当它的能力不足时。{/ p>

与容量相关的功能:

clear()  // Removes all elements from the vector.
empty()  // Returns true if the vector has no elements.
resize() // Changes the size of the vector.
size()  // Returns the number of items in the vector.

与尺寸相关的功能:

{{1}}

答案 1 :(得分:4)

是的,reserve(n)将在不实际放置元素的情况下分配空间 - 增加capacity()而不增加size()

顺便说一句,如果“添加到用户输入”是指用户点击“插入X”并将X插入向量,则无需担心调整大小的开销。等待用户输入比amortized constant调整大小性能慢很多倍。

答案 2 :(得分:1)

你的问题有点令人困惑,所以让我试着回答一下我的想法。

假设你有一个默认构造的vector<B>。然后,您致电vec.reserve(100)。现在,vec包含0个元素。它是空的。 vec.empty()返回truevec.size()返回0.每次调用push_back时,您都会插入一个元素,除非vec包含100个元素,否则会有没有重新分配。