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

发布于 2024-08-30 09:26:41 字数 452 浏览 1 评论 0原文

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

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

我想为这些向量分配内存以使其尽可能大,因为添加到它们是由用户输入控制的,所以我不希望频繁调整大小。然而,我每秒会多次迭代这个向量,并且我当前只处理我标记为“活动”的对象。在每次迭代中都必须检查 B/C 类的布尔成员是愚蠢的。当我运行这个列表时,我什至不希望这些对象出现在我的迭代器中。

提前保留最大空间并使用 push_back 向向量添加新对象是否可以解决此问题?

I've got a two vectors in class A that contain other class objects B and C. I know exactly how many elements these vectors are supposed to hold at maximum. In the initializer list of class A's constructor, I initialize these vectors to their max sizes (constants).

If I understand this correctly, I now have a vector of objects of class B that have been initialized using their default constructor. Right? When I wrote this code, I thought this was the only way to deal with things. However, I've since learned about std::vector.reserve() and I'd like to achieve something different.

I'd like to allocate memory for these vectors to grow as large as possible because adding to them is controlled by user-input, so I don't want frequent resizings. However, I iterate through this vector many, many times per second and I only currently work on objects I've flagged as "active". To have to check a boolean member of class B/C on every iteration is silly. I don't want these objects to even BE there for my iterators to see when I run through this list.

Is reserving the max space ahead of time and using push_back to add a new object to the vector a solution to this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

尬尬 2024-09-06 09:26:41

向量有容量和大小。容量是已分配内存的元素数量。大小是向量中实际元素的数量。当向量的大小为0时,它是空的。因此,size()返回0,empty()返回true。这并没有说明此时向量的容量(这取决于自创建以来对向量进行的插入和擦除的数量等) )。 capacity() 会告诉您当前容量 - 即向量在必须重新分配其内部存储以容纳更多元素之前可以容纳的元素数量。

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

如果您确实发现添加到向量的频率足以导致发生多次重新分配,并且这是一个性能问题,那么您可以调用reserve(),它将设置容量至少达到给定值。通常,当您非常清楚您的向量可能包含多少个元素时,您就会执行此操作。但是,除非您知道这会导致性能问题,否则这可能是一个坏主意。它只会使你的代码变得复杂。并且恒定摊销时间通常足以避免性能问题。

正如您所提到的,您还可以使用给定数量的默认构造元素构造一个向量,但除非您确实想要这些元素,否则这将是一个坏主意。 vector 应该做到这一点,以便您在向其中插入元素时不必担心重新分配容器(就像您必须使用数组一样),以及其中的默认构造元素出于分配内存的目的,就击败了这一点。如果您确实想这样做,请使用 reserve()。但再次强调,除非您确定它会提高性能,否则不要为 reserve() 烦恼。正如另一个答案中指出的那样,如果您根据用户输入将元素插入到向量中,那么 I/O 的时间成本将远远超过重新分配的时间成本在相对罕见的情况下,向量的内存会耗尽容量。

容量相关功能:

capacity()  // Returns the number of elements that the vector can hold
reserve()   // Sets the minimum capacity of the vector.

尺寸相关功能:

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.

A vector has capacity and it has size. The capacity is the number of elements for which memory has been allocated. Size is the number of elements which are actually in the vector. A vector is empty when its size is 0. So, size() returns 0 and empty() returns true. That says nothing about the capacity of the vector at that point (that would depend on things like the number of insertions and erasures that have been done to the vector since it was created). capacity() will tell you the current capacity - that is the number of elements that the vector can hold before it will have to reallocate its internal storage in order to hold more.

So, when you construct a vector, it has a certain size and a certain capacity. A default-constructed vector will have a size of zero and an implementation-defined capacity. You can insert elements into the vector freely without worrying about whether the vector is large enough - up to max_size() - max_size() being the maximum capacity/size that a vector can have on that system (typically large enough not to worry about). Each time that you insert an item into the vector, if it has sufficient capacity, then no memory-allocation is going to be allocated to the vector. However, if inserting that element would exceed the capacity of the vector, then the vector's memory is internally re-allocated so that it has enough capacity to hold the new element as well as an implementation-defined number of new elements (typically, the vector will probably double in capacity) and that element is inserted into the vector. This happens without you having to worry about increasing the vector's capacity. And it happens in constant amortized time, so you don't generally need to worry about it being a performance problem.

If you do find that you're adding to a vector often enough that many reallocations occur, and it's a performance problem, then you can call reserve() which will set the capacity to at least the given value. Typically, you'd do this when you have a very good idea of how many elements your vector is likely to hold. However, unless you know that it's going to a performance issue, then it's probably a bad idea. It's just going to complicate your code. And constant amortized time will generally be good enough to avoid performance issues.

You can also construct a vector with a given number of default-constructed elements as you mentioned, but unless you really want those elements, then that would be a bad idea. vector is supposed to make it so that you don't have to worry about reallocating the container when you insert elements into it (like you would have to with an array), and default-constructing elements in it for the purposes of allocating memory is defeating that. If you really want to do that, use reserve(). But again, don't bother with reserve() unless you're certain that it's going to improve performance. And as was pointed out in another answer, if you're inserting elements into the vector based on user input, then odds are that the time cost of the I/O will far exceed the time cost in reallocating memory for the vector on those relatively rare occasions when it runs out of capacity.

Capacity-related functions:

capacity()  // Returns the number of elements that the vector can hold
reserve()   // Sets the minimum capacity of the vector.

Size-related functions:

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.
你穿错了嫁妆 2024-09-06 09:26:41

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

顺便说一句,如果“添加到它们是由用户输入控制”意味着用户点击“插入 X”并且将 X 插入向量中,则无需担心调整大小的开销。等待用户输入比摊销常量调整大小性能慢很多倍。

Yes, reserve(n) will allocate space without actually putting elements there - increasing capacity() without increasing size().

BTW, if "adding to them is controlled by user-input" means that the user hits "insert X" and you insert X into the vector, you need not worry about the overhead of resizing. Waiting for user input is many times slower than the amortized constant resizing performance.

神妖 2024-09-06 09:26:41

你的问题有点令人困惑,所以让我尝试回答我认为你问的问题。

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

Your question is a little confusing, so let me try to answer what I think you asked.

Let's say you have a vector<B> which you default-construct. You then call vec.reserve(100). Now, vec contains 0 elements. It's empty. vec.empty() returns true and vec.size() returns 0. Every time you call push_back, you will insert one element, and unless vec conatins 100 elements, there will be no reallocation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文