Can vector of vectors get reallocated because one of elements got reallocated? - c++

Lets say I have a vector of vectors:
vector< vector<int> > table;
I know that vector can get reallocated if it doesn't have sufficient capacity.
I am wondering if there is a possibility of vector table reallocating if I do this:
table[i].resize(1000);
Is it possible that reallocation of table[i] also reallocates table?

No. This will not cause a reallocation in table.
The only operator/function called on table is the [] operator, which promises constant time. If re-allocation happened, this would violate the constant time promise.
The reason why you can change the vector size of the sub-vectors (the table[i]s) without requiring additional space to be allocated in the top-level vector is a vector's storage is managed via a pointer to a block of memory. Thus, increasing the amount of elements that a vector uses doesn't actually change the size of the vector object.
table[i].size() changes without changing sizeof(table[i]).

No, it won't have any incidence: the implementation of vectors is based on an array in most case (it's pretty much the idea of vectors), though this is not set in stone in the language specification. At any rate, the dynamic nature of vectors precludes any form of sequence inlined in the data structure, ie. the sequence of elements managed by the vector class cannot be inside the vector class, but is necessarily a chunck of memory located elsewhere, with a pointer in the class.
Your datatype is therefore similar to a dynamic array of pointers to dynamic arrays. Reallocating one pointed array will not have an effect on the pointer array.

No, because the content of table is unchanged - it still contains exactly the same instances as before. Only the storage of table[i] needed to be reallocated. vector contains a pointer to the storage - the size of vector object is always the same, only the referenced array can grow or shrink. Therefore, table[i] is not growing, if that's what you ask - only the array it points to is.

No. Calling a method of a vector's element wouldn't affect the vector itself.
Consider this as the following call: parent_object.child_object.Method(), where child_object knows nothing about the parent_object. The Method() cannot change state of parent_object.
The same goes for the vector of vectors. (Technically, here you are storing an array of pointers to arrays. Resizing one of the child arrays is a local operation and changes the appropriate pointer, but doesn't change the size of parent array.)

No, that can't happen. resize doesn't change the size of the vector object – it only changes the dynamic storage that the vector manages. So from the point of view of the outer vector, all the elements remain unchanged (and have the same, small size).

Related

When it comes to a sequence, is "vector[n].push_back()" is always O(1)?

I've used vector<int> v[N] a lot.
It's a very powerful tool for me.
I wonder v[n].push_back() costs O(1) on average.
I know when the vector is full, it needs to expand into double.
But isn't the sequence of vectors attached to each other?
If so, I think all vectors need to shift to the left which means it costs more than O(n).
To sum up, when it comes to sequence of vector, is v[n].push_back() always O(1)?
Please give me some help :D
It's not always O(1) anyway. See here (emphasis mine):
Complexity
Constant (amortized time, reallocation may happen).
If a reallocation happens, the reallocation is itself up to linear in
the entire size.
So even with just one vector, it's not guaranteed to be constant.
But isn't the sequence of vector attached each other? If so, I think
all vectors need to be shift which means it costs more than O(1).
This doesn't affect the runtime. The vectors in the array are independent of each other and manage their own storage dynamically (and separate from each other). The actual vector object in the array is always of the same size. When you modify an object in an array, it doesn't change the size of the object and move the rest of the array.
If so, I think all vectors need to shift to the left which means it costs more than O(n).
No thats not the case.
std::vectors dynamically allocate memory for an array to place the elements inside and merely store a pointer to that array (together with size and capacity). sizeof(std::vector<T>) is a compile-time constant. The amount of memory occupied by a std::vector inside a c-array does not change when you add elements to the vectors.
Hence, complexity of push_back is not effected by placing the vector in an array.

Is a vector of lists really a vector?

Not a code problem, but I finished a program that saves a vector of lists, but I suddenly thought... If the elements a vector are contiguous in memory, but a list needs pointers because it isn't contiguous memory.
A vector of lists is actually contiguous, if its elements are not? (In C++ language).
Yes, it just means the the vector elements are of type list and the data for these elements are contiguous in memory. However, "inside" the list elements there may be pointers to other memory locations. In essence, not everything that is referenced in vector elements is contiguous in memory but the references themselves are.
A vector of lists is actually contiguous, if its elements are not?
Yes and no.
From the vector's perspective it's still contiguous. The immediate data of every element, every std::list, is contiguous.
But that's just its internal pointers and such. In turn every actual element of each std::list is hidden away behind another layer of indirection.
So the ultimate data is not stored contiguously.
Is a vector of lists really a vector?
Well, that depends on what you mean by "vector" and how strict you want to be with that definition.
Welcome to abstractions!

std::vector and pointer predictability

when you push_back() items into an std::vector, and retain the pointers to the objects in the vector via the back() reference -- are you guaranteed (assuming no deletions occur) that the address of the objects in the vector will remain the same?
It seems like my vector changes the pointers of the objects I use, such that if I push 10 items into it, and retain the pointers to those 10 items by remembering the back() reference after each push_back.
if your vector is to store objects, not pointers to objects, are the addresses of those objects subject to constant change upon pushing more items?
Any method that causes the vector to resize itself will invalidate all iterators, pointers, and references to the elements contained within. This can be avoided by reserving mememory, or using boost::stable_vector.
23.3.6.5/1:
Remarks: Causes reallocation if the new size is greater than the old capacity. If no reallocation happens,
all the iterators and references before the insertion point remain valid.
No, std::vector is not a stable container, i.e. pointers and iterators may get invalidated by resizing the vector (or, better, by the corresponding reallocation). If you want to avoid this behaviour, use boost::stable_vector or std::list or std::deque instead (I would prefer the last). Or, more easily, you can simply store your locations by indices.
For more information, consider also the answer to this question here.
It's not guaranteed. If you push_back enough items to exceed the size of the memory buffer that's the backing store of the vector, a new buffer will be created, all the contents will be copied to the new location, and the old buffer will be deleted. At that point, old pointers (as well as iterators!) will be invalid.
If you know exactly how much maximum space you will ever need, you could set the size of the vector's buffer to that size when you create it, to avoid reallocation. However, I prefer to store "references" to elements of a vector as a reference to the vector and a size_t index into the vector, instead of using pointers. It's not necessarily slower than pointers (depending on the CPU type) but, even if it is, it won't be much slower and in my opinion it's worth it for the peace of mind knowing that no matter how the vector is used in the future or reallocated, it'll still refer to the proper element.

Effects of vector pushback on element address

I have a vector of class objects. A function randomly choses two elements and return their addresses.
Now using these two elements, I want to generate two new objects of the same class and add them to the vector by using push_back.
Here is the address of the two parent elements:
No problem here. The first child object is then generated, and I use vector_pushback to add it to the end of the vector. The problem is, after the push_back command has been executed, it seems like the addresses of the parent objects change. Here is the state of debugger after push_back:
As you can see, the addresses obviously stay the same, but it seems like they point to garbage values after push_back. To my understanding, push_back adds an element at the end of the vector. Therefore I expect the address of the 2 elements to not change at all.
What's wrong?
TL;DR version:
An insertion operation can invalidate any pointers, references or iterators to elements of a std::vector.
Full explanation:
A std::vector has two useful metrics:
size, which is the number of elements stored.
capacity, which is the number of elements it's currently capable of storing.
capacity >= size at all times.
The capacity is the length of the internal dynamically-allocated array.* When you insert an element, the size increments by 1. But once it reaches capacity, a new, larger array must be allocated (hence increasing the capacity). This requires all the elements to be copied across, and the originals to be deleted. So all their addresses change.
* This is the typical internal implementation of a std::vector.
push_back can cause reallocation and moving of all elements in the vector, if the space that's currently assigned for element storage cannot contain the new element.

When we called rezise member function of Vector(STL Type) type variable, content from vector remains constant or not?

I am using a vector variable.
std::vector<> mArray;
when i need to resize this variable i called mArray.resize() function. Does that keep the content of mArray remains same?
Thanks in advance.
resize() adds or removes elements, depending on the size you pass to resize().
If you just want to allocate space for future elements, use reserve() instead.
Yes, the elements already in the vector keep their values, at least if you didn't shrink the vector, then the last elements will be lost, of course. The new elements (if you grow the vector) will be standard constructed (or copied from the optional value argument).
As others have said, if you're growing the vector the contents up to the original size will be the same, and if you're shrinking the vector only the contents at the end are lost.
A point to emphasize is that this depends on the copy constructors and operator= of the contained objects being implemented correctly. The resized vector may not contain the original objects, but copies of those objects.
when i need to resize this variable i called mArray.resize()
function. Does that keep the content of mArray remains same?
It depends:
1>
When the new size is bigger than then current size, yes, the existing content remains the same. New object will be appended to the content using default constructor or value initialization.
2>
When the new size is smaller than then current size, the vector will shrink to new size and some content will be lost.