I am looking for a C++ data type similar to std::vector but without the overhead related to dynamic resizing. The size of the container will remain constant over its lifetime. I considered using boost::array, however, that is not appropriate because it requires the size of the array to be known at compile time, which is not the case in my situation.
Measure if the dynamic resizing has really any performance impact before using anything non-standard.
Tip: With vector.reserve there will never be any array-reallocation.
There's no overhead in reallocation if you don't reallocate std::vector. So either:
construct the std::vector with a known size ahead (std::vector x(100))
call reserve(n) after construction to make sure that at least n elements can be pushed into the vector before reallocation occurs.
The overhead induced by dynamic resizing capability of std::vector is virtually non-existent.
If you needed an array of compile-time size, looking for something more efficient than std::vector would indeed be a good idea in many cases.
But the difference between fixed run-time size and dynamic run-time size is negligible. std::vector is a perfect solution in this case.
I've used a template class based on ideas from STLSoft's auto_buffer (I cobbled together my own implementation from Matthew Wilson's Imperfect C++ book along with some ideas from the STLSoft implementation). It allocates the array by default on the stack (or embedded in the class object) if it's small enough (based on a template parameter you provide). If your runtime allocation is larger than that, the array storage comes from the heap.
http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html
So the nice thing about this class is that for smaller small sizes, the allocation is essentially a no-op.
If the size of the array is not known at compile time, then the only option in C++ is a dynamically-allocated array. You can use a std::vector to guarantee RAII. As others have said, the fact that std::vectors can be resized doesn't mean that you have to resize them. Create the std::vector with the correct size, and then don't call anything that would resize it.
Related
In this set of slides the author highly recommends to avoid pointers in C++ programs. Specially in slide 6, using vectors are suggested instead of dynamic arrays. While I believe vectors are much safer to use, for example they avoid memory leaks when an exception happens, they have extra memory overhead. This post says that vectors can consume up to twice the size of existing elements in the vector. Unfortunately, this feature causes my program to abort in my system with limited amount of available memory.
Is there a C++ container similar to dynamic arrays, getting the fixed (or rarely changing) number of elements in runtime, and provide the same safety as containers? The closest thing I could find (here) was array which required compile-time specified size provided in template.
You can use the array specialization of std::unique_ptr:
std::unique_ptr<int[]> arr(new int[5]);
This will safely manage the memory for you.
If you know the fixed size, just calling reserve(n) on the vector should do the trick. While it isn't guaranteed not to use more space, I don't know of any implementations that don't just allocate space for exactly that number of elements (assuming it is greater than the current capacity(), of course).
I know that manual dynamic memory allocation is a bad idea in general, but is it sometimes a better solution than using, say, std::vector?
To give a crude example, if I had to store an array of n integers, where n <= 16, say. I could implement it using
int* data = new int[n]; //assuming n is set beforehand
or using a vector:
std::vector<int> data;
Is it absolutely always a better idea to use a std::vector or could there be practical situations where manually allocating the dynamic memory would be a better idea, to increase efficiency?
It is always better to use std::vector/std::array, at least until you can conclusively prove (through profiling) that the T* a = new T[100]; solution is considerably faster in your specific situation. This is unlikely to happen: vector/array is an extremely thin layer around a plain old array. There is some overhead to bounds checking with vector::at, but you can circumvent that by using operator[].
I can't think of any case where dynamically allocating a C style
vector makes sense. (I've been working in C++ for over 25
years, and I've yet to use new[].) Usually, if I know the
size up front, I'll use something like:
std::vector<int> data( n );
to get an already sized vector, rather than using push_back.
Of course, if n is very small and is known at compile time,
I'll use std::array (if I have access to C++11), or even
a C style array, and just create the object on the stack, with
no dynamic allocation. (Such cases seem to be rare in the
code I work on; small fixed size arrays tend to be members of
classes. Where I do occasionally use a C style array.)
If you know the size in advance (especially at compile time), and don't need the dynamic re-sizing abilities of std::vector, then using something simpler is fine.
However, that something should preferably be std::array if you have C++11, or something like boost::scoped_array otherwise.
I doubt there'll be much efficiency gain unless it significantly reduces code size or something, but it's more expressive which is worthwhile anyway.
You should try to avoid C-style-arrays in C++ whenever possible. The STL provides containers which usually suffice for every need. Just imagine reallocation for an array or deleting elements out of its middle. The container shields you from handling this, while you would have to take care of it for yourself, and if you haven't done this a hundred times it is quite error-prone.
An exception is of course, if you are adressing low-level-issues which might not be able to cope with STL-containers.
There have already been some discussion about this topic. See here on SO.
Is it absolutely always a better idea to use a std::vector or could there be practical situations where manually allocating the dynamic memory would be a better idea, to increase efficiency?
Call me a simpleton, but 99.9999...% of the times I would just use a standard container. The default choice should be std::vector, but also std::deque<> could be a reasonable option sometimes. If the size is known at compile-time, opt for std::array<>, which is a lightweight, safe wrapper of C-style arrays which introduces zero overhead.
Standard containers expose member functions to specify the initial reserved amount of memory, so you won't have troubles with reallocations, and you won't have to remember delete[]ing your array. I honestly do not see why one should use manual memory management.
Efficiency shouldn't be an issue, since you have throwing and non-throwing member functions to access the contained elements, so you have a choice whether to favor safety or performance.
std::vector could be constructed with an size_type parameter that instantiate the vector with the specified number of elements and that does a single dynamic allocation (same as your array) and also you can use reserve to decrease the number of re-allocations over the usage time.
In n is known at compile-time, then you should choose std::array as:
std::array<int, n> data; //n is compile-time constant
and if n is not known at compile-time, OR the array might grow at runtime, then go for std::vector:
std::vector<int> data(n); //n may be known at runtime
Or in some cases, you may also prefer std::deque which is faster than std::vector in some scenario. See these:
C++ benchmark – std::vector VS std::list VS std::deque
Using Vector and Deque by Herb Sutter
Hope that helps.
From a perspective of someone who often works with low level code with C++, std vectors are really just helper methods with a safety net for a classic C style array. The only overheads you'd experience realistically are memory allocations and safety checks for boundaries. If you're writing a program which needs performance and are going to be using vectors as a regular array I'd recommend to just use C style arrays instead of vectors. You should realistically be vetting the data that comes into the application and check the boundaries yourself to avoid checks on every memory access to the array.
It's good to see that others are checking the differences of the C ways and the C++ ways. More often than not C++ standard methods have significantly worse performance and uglier syntax than their C counterparts and is generally the reason people call C++ bloated. I think C++ focuses more on safety and making the language more like JavaScript/C# even though the language fundamentally lacks the foundation to be one.
This question already has answers here:
std::vector versus std::array in C++
(6 answers)
Closed 6 years ago.
What is the difference between std::array and std::vector? When do you use one over other?
I have always used and considered std:vector as an C++ way of using C arrays, so what is the difference?
std::array is just a class version of the classic C array. That means its size is fixed at compile time and it will be allocated as a single chunk (e.g. taking space on the stack). The advantage it has is slightly better performance because there is no indirection between the object and the arrayed data.
std::vector is a small class containing pointers into the heap. (So when you allocate a std::vector, it always calls new.) They are slightly slower to access because those pointers have to be chased to get to the arrayed data... But in exchange for that, they can be resized and they only take a trivial amount of stack space no matter how large they are.
[edit]
As for when to use one over the other, honestly std::vector is almost always what you want. Creating large objects on the stack is generally frowned upon, and the extra level of indirection is usually irrelevant. (For example, if you iterate through all of the elements, the extra memory access only happens once at the start of the loop.)
The vector's elements are guaranteed to be contiguous, so you can pass &vec[0] to any function expecting a pointer to an array; e.g., C library routines. (As an aside, std::vector<char> buf(8192); is a great way to allocate a local buffer for calls to read/write or similar without directly invoking new.)
That said, the lack of that extra level of indirection, plus the compile-time constant size, can make std::array significantly faster for a very small array that gets created/destroyed/accessed a lot.
So my advice would be: Use std::vector unless (a) your profiler tells you that you have a problem and (b) the array is tiny.
I'm going to assume that you know that std::array is compile-time fixed in size, while std::vector is variable size. Also, I'll assume you know that std::array doesn't do dynamic allocation. So instead, I'll answer why you would use std::array instead of std::vector.
Have you ever found yourself doing this:
std::vector<SomeType> vecName(10);
And then you never actually increase the size of the std::vector? If so, then std::array is a good alternative.
But really, std::array (coupled with initializer lists) exists to make C-style arrays almost entirely worthless. They don't generally compete with std::vectors; they compete more with C-style arrays.
Think of it as the C++ committee doing their best to kill off almost all legitimate use of C-style arrays.
std::array
is an aggregate
is fixed-size
requires that its
elements be default constructible (vs
copy (C++03) or move (C++0x)
constructible)
is linearly
swappable (vs constant time)
is linearly movable (vs constant time)
potentially pays one less indirection than std::vector
A good use case is when doing things 'close-to-the-metal', while keeping the niceties of C++ and keeping all the bad things of raw arrays out of the way.
Same reasoning when using a C-style static array rather than a std::vector. And for that, I kindly refer you to here.
std::array has a fixed (compile time) size, while std::vector can grow.
As such, std::array is like using a C array, while std::vector is like dynamically allocating memory.
I use my own personal hand coded Array<> template class, which has a simpler API compared with std::array or std::vector. For example:
To use a dynamic Array:
Array<> myDynamicArray; // Note array size is not given at compile time
myDynamicArray.resize(N); // N is a run time value
...
To use a static Array, fixed size at compile time:
Array<100> myFixedArry;
I believe it has a better syntax than std::array, or std::vector. Also extremely efficient.
I need to have a fixed-size array of elements and to call on them functions that require to know about how they're placed in memory, in particular:
functions like glVertexPointer, that needs to know where the vertices are, how distant they are one from the other and so on. In my case vertices would be members of the elements to store.
to get the index of an element within this array, I'd prefer to avoid having an index field within my elements, but would rather play with pointers arithmetic (ie: index of Element *x will be x - & array[0]) -- btw, this sounds dirty to me: is it good practice or should I do something else?
Is it safe to use std::vector for this?
Something makes me think that an std::array would be more appropriate but:
Constructor and destructor for my structure will be rarely called: I don't mind about such overhead.
I'm going to set the std::vector capacity to size I need (the size that would use for an std::array, thus won't take any overhead due to sporadic reallocation.
I don't mind a little space overhead for std::vector's internal structure.
I could use the ability to resize the vector (or better: to have a size chosen during setup), and I think there's no way to do this with std::array, since its size is a template parameter (that's too bad: I could do that even with an old C-like array, just dynamically allocating it on the heap).
If std::vector is fine for my purpose I'd like to know into details if it will have some runtime overhead with respect to std::array (or to a plain C array):
I know that it'll call the default constructor for any element once I increase its size (but I guess this won't cost anything if my data has got an empty default constructor?), same for destructor. Anything else?
Vectors are guaranteed to have all elements in contigous memory, so it is safe to use in your scenario. There can be a small performance hit compared to c-style arrays, for instance due to index validations done by the vector implementation. In most cases, the performance is determined by something else though, so I wouldn't worry about that until actual measurements of performance show that this a real problem.
As pointed out by others, make sure that you don't reallocate the vector while you are making use of the data stored in it if you are using pointers to elements (or iterators) to access it.
It's fine to treat the data in a std::vector as an array, get a pointer to the start of it with &v[0]. Obviously if you do anything that can reallocate the data then then you pointers will probably be invalidated.
Yep, You can use it as Array in OpenGL :) Example:
glBufferData( GL_ARRAY_BUFFER_ARB, dataVec.size() * sizeof( dataVec[0] ), &dataVec[0], GL_STATIC_DRAW_ARB );
Where dataVec is std::Vector
It is even safer than having an array on the stack: how big really is your stack? how big could your array become (fixed size, but the size could be increased in later versions)?
If you really want a std::array you can use boost::array. It is like a common array, but support iterators and you can easily use it with STL algorithms.
Working in multithreading environment and dynamic memory allocation might cause problem because vector is usually a continuous chunk of memory and of pointers might not!
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.