Question

I can think of three ways of filling a std::vector

Suppose we have

vector<int> v(100, 0);

Then I want it to hold (1, 1, 1). We can do:

v.clear();
v.resize(3, 1);

Or

v = vector<int>(3, 1);

And I learned another approach:

vector<int>(3, 1).swap(v); 

First question is: Is any of them the best approach?

Second question: suppose v was declared outside the main function. According to this answer, the memory will be allocated in the data segment. If I use the second or third approach, will the memory be allocated on the stack?

Was it helpful?

Solution

So, here's the differences and I'll let you decide what is best for your situation.

v.clear();
v.resize(3, 1);

In this case we have marked the vector as cleared. It still holds whatever it allocated in order to hold 100 elements (which can be more than the space necessary for 100 elements). Then we added 3 items with value of 1. All this did was increase the size counter and reset 3 values, the underlying memory is still the same size.

v = vector<int>(3, 1);

This does pretty much the same thing except that an extra vector temporary is created and instead of there being intermittent places where the counter is 0 and then 3 with some values, it simple copies the counter size and then does an operation similar to a memcpy to copy over the 3 elements. Size of underlying memory allocated for v is still enough to hold 100 integers.

vector<int>(3, 1).swap(v); 

This one is significantly different. In this case we create a temporary vector that holds 3 elements that are all initialized to 1. Theoretically it could still have enough memory reserved for 100 elements but the chances are it has much less. Then we swap this vector with our own and let the temporary get destroyed. This has the added benefit of clearing out any extra memory allocated by our old vector that wasn't in the temporary. The way this works is that the two vectors (our v and the temporary) swap more than just counters and values, they also swap buffer pointers.

This is the only way to shrink a vector.

OTHER TIPS

How about you use the member of vector that is there for this task?

std::vector<int> v(100);
v.assign(3, 1); // this is what you should do.

To answer the second question first: vector will always dynamically allocate the memory for the objects it contains, so it will end up on the heap.

As to which method of reassigning is better, I'd say your first or second method make your intent most clear, and that's the most important attribute.

Swapping will effectively shrink the vector to 3 elements. The other ones will likely not.

vector<int> v(100);
v.assign(3, 1);
assert(v.size() == 3);
assert(v.capacity() != 3);

v = vector<int>(3, 1);
// Now, v.capacity() is likely not to be 3.

vector<int>(3, 1).swap(v);
assert(v.capacity() == 3);

The other approaches won't resize the vector internally. It still will occupy 100 * sizeof(int) bytes in memory, even if the size() member returns 3. Try displaying v.capacity() to convince yourself.

One issue, not mentioned in previous posts, is important in choosing among these alternatives. Namely, exception safety. The vector<int>(3, 1).swap(v); has strong exception safety guarantee. The form v = vector<int>(3, 1); might also offer such guarantee if assignment implemented in terms of swap. The first alternative is not safe: v.clear(); v.resize(3, 1);

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top