Can vector be resized bidirectionally? - c++

Is there any function to resize a vector in both directions?Can we manipulate the pointer or the element from where it starts adding new empty elements?

Here is the entire interface of std::vector. It makes it very obvious there's no direct way to do what you ask, although you can reserve and then insert(begin,...) if you really want to (it has linear complexity, so is usually avoided).
The usual advice would be to use std::deque instead, since it's specifically designed for this operation.

Yes, you can insert elements to the front of the vector using insert:
vec.insert(vec.begin(), numer_of_elements_to_insert, {});
Note, however, that front-inserting into a vector is very inefficient, because it will require moving all the current elements in the vector past the newly inserted ones. If you need a double-ended container, look into std::deque.

Related

Keeping constant number of elements in vector

I am trying to figure out the fastest way to keep constant number of elements in vector (or maybe there is some ready-made structure that do it automatically).
In my app I am adding multiple elements to the vector and I need to do it fast. Because of vector's self resizing at some point it is significantly decreasing overall application speed. What I was thinking about is to do something like this:
if(my_vector.size() < 300)
my_vector.push_back(new_element);
else
{
my_vector.pop_front();
my_vector.push_back(new_element);
}
but after first few tests I've realized that it might not be the best solution, because I am not sure if pop_front() and later push_back() doesn't still need to resize at some point.
Is there any other solution for this?
Use a std::queue. Its underlying container is a std::deque, but like a stack a queue's interface is specifically for FIFO operations (push_back, pop_front), which is exactly what you're doing in your situation. Here's why a deque is better for this situation:
The storage of a deque is automatically expanded and contracted as
needed. Expansion of a deque is cheaper than the expansion of a
std::vector because it does not involve copying of the existing
elements to a new memory location.
The complexity (efficiency) of common operations on deques is as
follows:
Random access - constant O(1)
Insertion or removal of elements at the end or beginning - constant O(1)
To implement a fixed-size container with push_back and pop_front and minimal memory shuffling, use a std::array of the appropriate size. To keep track of things you'll need a front index for pushing elements and a back index for popping things. To push, store the element at the location given by front_index, then increment front_index and take the remainder modulo the container size. To pop, read the element at the location given by back_index, and adjust that index the same way you did front_index. With that in place, the code in the question will do what you need.
You just need to reserve the capacity to a reasonable number. The vector will not automatically shrink. So it only will grow and, possibly, stop at some point.
You might be also interested in the resize policies. For example Facebook made a substantial research and created own implementation of the vector - folly::fbvector which has better performance than std::vector

Inserting an element into vector in the middle

Is there an way of inserting/deleting an element from the vectors other than the following..
The formal method of using 'push_back'
Using 'find()' in this way... find(v.begin(), v.end(), int)
I have read some where that inserting in the middle can be achieved by inclusive insertion/deletion.
So, is it really possible?
You can use std::vector::insert; however, note that this operation is O(.size()). If your code needs to perform insertions in the middle frequently, you may want to switch to a linked-list structure.
Is there an way of inserting/deleting an element from the vectors other than the following
Yes, you can use std::vector::insert() to insert element at a specified position.
Because vectors use an array as their underlying storage, inserting elements in positions other than the vector end causes the container to move all the elements that were after position to their new positions. This is generally an inefficient operation compared to the one performed for the same operation by other kinds of sequence containers (such as std::list).
std::vector is standard container, you could apply standard STL algorithms on it.
vector::insert seems to be what you want.

will stl deque reallocate my elements (c++)?

Hi I need an stl container which can be indexed like a vector but does not move old elements in the memory like a vector would do with resize or reserve (Unless I call reserve once at the beginning with a capacity enough for all elements, which is not good for me). (Note I do address binding to the elements so I expect the address of these elements to never change). So I've found this deque. Do you think it is good for this purpose? Important: I need only pushback but I need to grow the container on demand in small chunks.
std::deque "never invalidates pointers or references to the rest of the elements" when adding or removing elements at its back or front, so yes, when you only push_back the elements stay in place.
A careful reading of the documentation seems to indicate that so long as you insert at the beginning or the end it will not invalidate pointers, and invalidating pointers is a sign that the data is being copied or moved.
The way it's constructed is not quite like a linked list, where each element is allocated individually, but as a set of linked arrays presumably for performance reasons. Altering the order of elements in the middle will necessitate moving data around.

Resize and copy of c++ array

If I have for example array of pointers (which is full) with 5 elements and I want to insert another element at second position, I would have to allocate another array (with size+1), copy first element from an old array, insert new element, and then copy remaining elements. This application can't waste any space.
This is the code so far:
Sometype **newArray=new Sometype*[++Count];
size_t s=sizeof(Array);
memcpy(newArray,Array,s*position);
newArray[position]=new Sometype();
memcpy(newArray+position+1,Array+position,s*(Count-position-1));
delete [] Array;
Array=newArray;
Is there any more efficient method to do this thing because this is a bottleneck for my application?I'm new to c++ so I don't know any advanced stuff.
Could vector be used for this purpose?
I think I read somewhere that it takes double of previous used space when it's resizing.
Is this true or this behavior can be modified?
If you can't waste any space and you have to stick to sequential containers, then I'm afraid this is the most efficient way. But I still don't believe that you can't waste any space. If you can anticipate in advance that you will need to later add 5 more elements, then having your array resized from the beginning will prove much more effective. In any case, you should use vector to avoid this awful C-style code and be more clear with your intents. You might want to take a look at std::vector<T>::reserve() function. Whether or not vector takes double of previous when it's resizing is unspecified and varies across implementations.
Have a look at the standard containers std::vector, std::list, std::unordered_set and std::unordered_map

set vs vector with custom iterator

I understand this question may be quickly flagged as a duplicate of many other more popular questions, but I'll still ask it:
I need a container that provides duplicate checking on insert (like std::set, but allows me to modify elements already present (like std::vector). It should also be relatively fast to search for elements (which would prefer std::set again). Would it be better to use a vector and perhaps a custom duplicate-checking insert_iterator instead of modifying set elements by erasing and reinserting them?
Thanks
What is to stop you from using a std::set? If you need to modify an element, copy it, erase it, then re-insert.
Have you looked into using a map?
Reference
A map may be a good solution to your problem.
If your strings are long and performance is critical then you may be stuck with a custom container that wraps something like a parallel vector<string> and set<string *>. Provide a custom comparator for the set so that it dereferences through the pointer to make the comparisons. To modify an element, remove the pointer from the set, modify the string, then reinsert the pointer.
This get a bit messy when you want to remove container elements, so you would want to use some form of lazy deletion. At that point you are very close to a full-blown free-object pool for your strings.
If you're using a vector of strings in performance-critical code, then watch out for the vector reallocations which would manually copy each string into the new memory chunk. You can bypass that by watching for an upcoming reallocation, creating a new vector of empty strings (pre-reserved to double size), and then using string::swap on each element to move the old data into the new larger vector.
Things will be much nicer when c++0x move semantics are widely available.