Related
I saw the following from this link:
Vectors are part of STL. Vectors in C++ are sequence containers representing arrays that can change their size during runtime . They use contiguous storage locations for their elements just as efficiently as in arrays, which means that their elements can also be accessed using offsets on regular pointers to its elements.
Vectors are the dynamic arrays that are used to store data.It is different from arrays which store sequential data and are static in nature, Vectors provide more flexibility to the program. Vectors can adjust their size automatically when an element is inserted or deleted from it.
If vectors can do so much, under what circumstances do we still prefer arrays?
Thanks!
If vectors can do so much, under what circumstances do we still prefer arrays?
A good design is not when there is nothing left to add, rather when there is nothing left to remove. Or introducing extra complexity only when it is needed.
One major disadvantage of std::vector is that it uses dynamic memory allocation whenever it must grow, which can be quite expensive in terms of execution time. Therefore, in situations when a reasonable upper limit is known, it may be better to use a fixed-length array, even if this wastes memory space. This decision is a space/time trade-off.
However, this disadvantage of std::vector can be mitigated by reserving memory for a certain amount of elements in advance, by calling std::vector::reserve.
Another disadvantage of using std::vector is that serialization is significantly harder. For example, if you make a std::array a member of a struct, then you can simply copy the entire struct contents byte by byte in order to serialize it. However, this is not possible if you make a std::vector a member of a struct, as it will probably not store the actual data inside the struct, but will probably only store a pointer to the data. Therefore, you will be unable to serialize the struct by simply copying the memory of the struct. Instead, serializing the std::vector will require special treatment.
What is the safe, portable, idiomatic way to use the spare capacity in a std::vector?
std::vector<Foo> foos;
foos.emplace_back(1);
foos.emplace_back(2);
foos.reserve(10);
At this point, foos owns at least 8 * sizeof(Foo) uninitialized spare memory starting at foos.data() + foos.size(). It seems terribly inefficient to let that memory go to waste. How can I use this spare capacity as scratch space or for other purposes before I fill it with Foo objects by appending to foos? What is the right way to do this without invoking any undefined behavior?
How can I use the spare capacity in a std::vector?
By inserting more elements.
More convoluted answer which may be what you're looking for, but probably more complex than it's worth:
You can allocate memory yourself (std::allocator or whatever; don't forget std::unique_ptr), and implement a custom allocator that uses that piece of memory. You can then use that memory for whatever and later create a vector using the custom allocator. Note that this doesn't let you use the memory that has already been reserved for the vecor; you can only use the memory before it has been acquired by the vector.
Yes, memory for unused elements is wasted, but it is unavoidable. It's by design.
The storage of the vector is handled automatically, being expanded and
contracted as needed. Vectors usually occupy more space than static
arrays, because more memory is allocated to handle future growth. This
way a vector does not need to reallocate each time an element is
inserted, but only when the additional memory is exhausted.
It's also good to know some non-standard vector's variants and may use them as replacement for std::vector, they
have specific application scenarios.
If you need a dynamic array and the maximum capacity is know at compile time,then boost::static_vector would be a choice(Use it may avoid the unnecessary memory waste of std::vector since most of std::vector's implementation always reserve capacity with a pow of 2, so if your desired capacity is 10, then 6 elements is likely to
be waste):
static_vector is an hybrid between vector and array: like vector, it's
a sequence container with contiguous storage that can change in size,
along with the static allocation, low overhead, and fixed capacity of
array. static_vector is based on Adam Wulkiewicz and Andrew Hundt's
high-performance varray class.
The number of elements in a static_vector may vary dynamically up to a
fixed capacity because elements are stored within the object itself
similarly to an array. However, objects are initialized as they are
inserted into static_vector unlike C arrays or std::array which must
construct all elements on instantiation. The behavior of static_vector
enables the use of statically allocated elements in cases with complex
object lifetime requirements that would otherwise not be trivially
possible. Some other properties:
Random access to elements Constant time insertion and removal of
elements at the end Linear time insertion and removal of elements at
the beginning or in the middle. static_vector is well suited for use
in a buffer, the internal implementation of other classes, or use
cases where there is a fixed limit to the number of elements that must
be stored. Embedded and realtime applications where allocation either
may not be available or acceptable are a particular case where
static_vector can be beneficial.
And if the dynamic array mostly has a very small size(only some of them would be large but with a small probability), then we may consider using small_vector, a small vector will improve the performance for such a scenario and such container is widely used in large projects.
small_vector is a vector-like container optimized for the case when it
contains few elements. It contains some preallocated elements
in-place, which allows it to avoid the use of dynamic storage
allocation when the actual number of elements is below that
preallocated threshold. small_vector is inspired by LLVM's SmallVector
container. Unlike static_vector, small_vector's capacity can grow
beyond the initial preallocated capacity.
I need something that behaves like an std::vector (interface/features/etc.) but I need it to be flat, i.e. it mustn't dynamically allocate a buffer. Clearly, this doesn't work in general, as the available size must be determined at compile time. But I want the type to be able to deal with N objects without additional allocations, and only if further items are pushed resort to dynamic allocation.
Some implementations of std::vector already do this, but only to the extent that it uses its existing members if the accumulated size of the content fits (I believe about three pointers-worth of payload). So, firstly, this is not a guarantee and secondly it is not configurable at compile time.
My thoughts are that I could either
A) self-cook a type (probably bad because I'd loose the ridiculous performance optimisations from vector)
B) use some sort of variant<vector<T>,array<T,N>> with an access wrapper (oh, the boilerplate)
C) come up with a MyAllocator<T,N> that has an array<T,N> member which then may be used to hold the first N items and after this defer to allocator<T> but I'm not sure if this can work because I cannot find out whether vector must permanently hold an instance of its allocator type as a member (I believe it does not)
I figure I'm not the first person to want this, so perhaps there are already approaches to this? Some empirical values or perhaps even a free library?
You might find folly/small_vector of use.
folly::small_vector is a sequence container that
implements small buffer optimization. It behaves similarly to
std::vector, except until a certain number of elements are reserved it
does not use the heap.
Like standard vector, it is guaranteed to use contiguous memory. (So,
after it spills to the heap all the elements live in the heap buffer.)
Simple usage example:
small_vector<int,2> vec;
vec.push_back(0); // Stored in-place on stack
vec.push_back(1); // Still on the stack
vec.push_back(2); // Switches to heap buffer.
// With space for 32 in situ unique pointers, and only using a
// 4-byte size_type.
small_vector<std::unique_ptr<int>, 32, uint32_t> v;
// A inline vector of up to 256 ints which will not use the heap.
small_vector<int, 256, NoHeap> v;
// Same as the above, but making the size_type smaller too.
small_vector<int, 256, NoHeap, uint16_t> v;
What is the exact difference between dynamic arrays and vectors. It was an interview question to me.
I said both have sequential memory.
Vectors can be grown in size at any point in the code. He then said even dynamic arrays can be grown in size after creating.
I said vectors are error free since it is in the standard library. He said he will provide as .so file of dynamic arrays which is error free and has all the qualities on par with STL.
I am confused and didn't answer the exact difference. When I searched on Internet, I had seen the above statements only.
Can someone please explain me the exact difference? And what was the interviewer expecting from me?
He said he will provide as .so file of dynamic arrays which is error free and has all the qualities on par with STL.
If his dynamic array class does the same as std::vector (that is: it implements RAII to clean up after itself, can grow and shrink and whatever else std::vector does), then there's only one major advantage std::vector has over his dynamic array class:
std::vector is standardized and everybody knows it. If I see a std::vector in some piece of code, I know exactly what it does and how it is supposed to be used. If, however, I see a my::dynamic_array, I do not know that at all. I would need to have to look at its documentation or even — gasp! — implementation to find out whether my_dynamic_array::resize() does the same as std::vector::resize().
A great deal here depends on what he means by a "dynamic array". Most people mean something where the memory is allocated with array-new and freed with array-delete. If that's the intent here, then having qualities on a par with std::vector simply isn't possible.
The reason is fairly simple: std::vector routinely allocates a chunk of memory larger than necessary to hold the number of elements currently being stored. It then constructs objects in that memory as needed to expand. With array-new, however, you have no choice -- you're allocating an array of objects, so if you allocate space for (say) 100 objects, you end up with 100 objects being created in that space (immediately). It simply has no provision for having a buffer some part of which contains real objects, and another part of which is just plain memory, containing nothing.
I suppose if yo want to stretch a point, it's possible to imitate std::vector and still allocate the space with array-new. To do it, you just have to allocate an array of char, and then use placement new to create objects in that raw memory space. This allows pretty much the same things as std::vector, because it is nearly the same thing as std::vector. We're still missing a (potential) level of indirection though -- std::vector actually allocates memory via an Allocator object so you can change exactly how it allocates its raw memory (by default it uses std::allocator<T>, which uses operator new, but if you wanted to, you could actually write an allocator that would use new char[size], though I can't quite imagine why you would).
You could, of course, write your dynamic array to use an allocator object as well. At that point, for all practical purposes you've just reinvented std::vector under a (presumably) new name. In that case, #sbi is still right: the mere fact that it's not standardized means it's still missing one of the chief qualities of std:::vector -- the quality of being standardized and already known by everybody who knows C++. Even without that, though, we have to stretch the phrase "dynamic array" to (and I'd posit, beyond) the breaking point to get the same qualities as std::vector, even if we ignore standardization.
I expect they wanted you to talk about the traps of forgetting to delete the dynamic array with operator delete[] and then got confused themselves when they tried to help you along; it doesn't make much sense to implement a dynamic array as a plain class since it bakes in the element type.
The array memory allocated for vectors is released when the vector goes out of scope, in case the vector is declared on the stack (the backing array will be on the heap).
void foo() {
vector<int> v;
// ... method body
// backing array will be freed here
}
It says here: "Internally, vectors use a dynamically allocated array to store their elements."
Underlying concept of vectors is dynamically allocated array.
http://www.cplusplus.com/reference/vector/vector/
Maybe it's that dynamic array you would go through the copy process to a new dynamic array whenever you want to resize, but you are able to control when it does that depending on your knowledge of the data going into the array.
Whereas a vector uses the same process, but a vector does not know if it will grow or not later, so it probably allocates extra storage for possible growth in size, therefore it COULD possibly consume more memory space than intended to manage itself compared to dynamic arrays.
So, I'd say the difference is to use a vector when managing it's size is not a big deal, where you would use a dynamic array when you would rather do the resizing yourself.
Arrays have to be deallocated explicitly if defined dynamically whereas vectors are automatically de-allocated from heap memory.
Size of array cannot be determined if dynamically allocated whereas Size of the vector can be determined in O(1) time.
3.When arrays are passed to a function, a separate parameter for size is also passed whereas in case of passing a vector to a function, there is no such need as vector maintains variables which keeps track of size of container at all times.
4.When we allocate array dynamically then after size is initialized we cannot change the size whereasin vector we can do it.
I have some questions about vector in STL to clarify.....
Where are the objects in vector allocated? heap?
does vector have boundary check? If the index out of the boundary, what error will happen?
Why array is faster than vector?
Is there any case in which vector is not applicable but array is a must?
In a contiguous memory block on the heap. A vector<int> allocates memory the same way new int[x] would.
Only if you use the at method. It throws an std::out_of_range exception if the boundary check fails. The operator[] doesn't perform bounds checking.
Because an array gives direct access to memory, while accessing a vector element most likely involves a method call. The difference can be ridiculously small though, especially if your compiler decides to inline the calls.
In general, you'll use a vector if you want your container to have a dynamic size, and a simple array if a known fixed size is enough. Be sure to check out the other containers, like deque and list, to be sure you pick the most appropriate one. Otherwise, if you need to deal with non-C++ APIs, you'll obviously need to have access to a regular array. (edit) #BillyONeal says you should use &vector[0] to get the address of the underlying array, but use it with care since it can change if the vector's capacity changes.
Where are the objects in vector
allocated? heap?
It depends on the STL implementation, but in all likelihood on the heap, yes.
does vector have boundary check? If the index out of the boundary,
what error will happen?
Yes, a vector grows dynamically, you can check its size using the capacity() member function. If it should run out of space, it generally allocates more space using the reserve() member function.
Why array is faster than vector?
Arrays can be faster because they are plain data that does not need to be accessed through a wrapper object such as vector. You can think of a vector as neatly packaged array for your convenience.
Is there any case in which vector is
not applicable but array is a must?
I think there can be times where an array is preferable over a vector. For example, when dealing with legacy C code or when speed is of utmost importance. But generally you can solve any array problem by containing the data in an STL vector.
Ad 4.: When dealing with legacy interfaces (e.g. POSIX) arrays may be a must.
On the heap (assuming you use the standard allocator, which is the default)
It is not boundary checked when using operator[], but it is if you use the member function at (e.g. my_vec.at(0)). If you use at and the index is out or bounds, it throws an std::out_of_range exception.
Arrays aren't generally faster. It depends whether or not the vector's operator[] calls are inlined or not. Most modern compilers should index it though, as it is just a single array index.
In general, normal arrays can be replaced by vectors. You shouldn't really use a std::vector on the public interface of a library, and manu library APIs require raw C-style arrays.
By default contents are allocated dynamically. (But I suppose you can provide an allocator that gets the memory from some place else.)
The at method does bounds checks and throws an out_of_range. Other methods may or may not check bounds, depending on implementation and settings.
I would assume a vector to be slower than an array when it does something different from an array. For example, dynamic allocation is costly, so vector has a cost that arrays don't have. Dynamically resizing a vector is costly, whereas an array can't be resized at all. I wouldn't expect to see any difference when accessing the elements (except for possible run-time checks done by the implementation which you should be able to turn off if desired).
I don't know of such a scenario. You can always get a pointer to the underlying array of a vector with &vec[0]. However, a vector can be an overkill if you don't need any of the features it provides - mostly the ability to (re)size it dynamically. In such cases an array could do just fine, but note that there are classes that make an array a first-class object too (std::tr1::array or boost::array) which make the array copyable and not decay into a pointer.