Here is what a typical vector remove-erase operation looks like :
auto toErase = std::remove_if(vec.begin(), vec.end(),
[val](obj_t const& obj) { return obj.myval == val; }
); // This actually moves objects around !
vec.erase(toErase, vec.end());
This works fine in the majority of cases, but I am faced with the case where obj_t type does not allow move or copy semantics. Objects are inserted with vec.emplace_back(), and I am looking for an alternative to remove_if that doesn't need either copy or move.
Does it already exist somewhere ? If not, how would it be built ?
If object is non-movable/copyable how do you expect to rearrange objects in the vector? Vector is a contiguous container - so you cannot erase an element in the middle without shifting the ending.
To resolve the issue, either make the object movable/copyable, wrap it in unique_ptr (thus making it movable), or use one of map/set/unordered_map containers as those don't relocate objects unlike std::vector
It is not possible to remove from std::vector without copy or move support: how will you handle case, when you delete something from the middle? You can use for example std::list<Class> or std::vector<std::shared_ptr<Class>> instead of std::vector<Class>.
Actually, if the main problem around remove_if: I recommend you use shared_ptr or unique_ptr
Related
I need to put an std::vector into an std::stack.
Here is my method so far(I am building a card game) :
void CardStack::initializeCardStack(std::vector<Card> & p_cardVector) {
m_cardStack = std::stack<Card>();
//code that should initialize m_cardStack with p_cardVector
}
Note : I cannot change my method signature because it is a imposed by a teacher...
Do I have to iterate over the whole vector ? What is the most efficient way to do this ? The documentation.
I have tried Jens answer but it didn't work.
std::stack doesn't have a constructor which accepts iterators, so you could construct a temporary deque and initialize the stack with this:
void ClassName::initializeStack(std::vector<AnotherClass> const& v) {
m_stackAttribute = std::stack<AnotherClass>( std::stack<AnotherClass>::container_type(v.begin(), v.end()) );
}
However, this copies each element into the container. For maximum efficiency, you should also use move-semantics to eliminate copies
void ClassName::initializeStack(std::vector<AnotherClass>&& v) {
std::stack<AnotherClass>::container_type tmp( std::make_move_iterator(v.begin()), std::make_move_iterator( v.end() ));
m_stackAttribute = std::stack<AnotherClass>( std::move(tmp) );
}
The most efficient way is not using an std::stack at all and just use a std::vector or even better for this use a std::deque.
I've seen and written a lot of C++ code (a lot) but I've yet to find any use for the stack stuff (any meaningful use, that is). It would be different if the underlying container could be changed or having its container type determined at runtime, but this is not the case.
To copy the elements from an std::vector into a std::deque you can just use
std::deque<T> stack(vec.begin(), vec.end());
This will allow the implementation to use the most efficient way to copy the elements.
To explicitly answer your question: yes, the only way to put elements in a stack is to push them in with a loop. This is not efficient but the stack interface doesn't define anything else. However who wrote code accepting an std::stack parameter should be fired (unless s/he promises that it will never happen again) and its code reverted to something more sensible: you would get the same (absence of) "flexibility" but a better interface.
The design problem of stack is that it's parametrized on the underlying container type while instead (to have any meaning) should have been parametrized on the contained element type and receving in the constructor a container for that type (thus hiding the container type). In its present form is basically useless.
I was wondering if it is OK to always use emplace to replace insert when inserting a single element into a STL container, like set, unordered_set?
From the signature, emplace is simpler and do not involve overloads. Is there any issue with stop using insert and use emplace all the time?
Note: there are SO questions asking about the difference between emplace and insert/push_back etc. (e.g. here, here, and here) I understand the difference, and it seems to me that emplace is better in every way. I just want to confirm if it's OK to deprecate insert.
There are some examples here that can be adapted to emplace and insert, showing when the behaviour may differ.
These examples may seem a bit artificial, so I'll give one that will hopefully appear less so:
#include <set>
template <typename T>
T id(T x) { return x; }
int main() {
std::set<int(*)(int)> s;
s.insert(id); // OK
s.emplace(id); // error
s.emplace(id<int>); // OK
}
insert can deduce the template parameter of id because it knows what type it wants. For emplace you get an error unless you explicitly specify.
Always? No, certainly not.
Consider the following example, which uses std::vector for simplicity (assume uptr is a smart pointer acting generally like std::unique_ptr):
std::vector<uptr<T>> vec;
vec.insert(vec.begin(), new T());
It is exception-safe. A temporary uptr is created to pass to insert, which is moved into the vector. If reallocation of the vector fails, the allocated T is owned by a smart pointer which correctly deletes it.
Compare to:
std::vector<std::uptr<T>> vec;
vec.emplace(vec.begin(), new T());
emplace is not allowed to create a temporary object. The uptr will be created once, in-place in the vector. If reallocation fails, there is no location for in-place creation, and no smart pointer will ever be initialized. The T will be leaked.
Of course, the best alternative is:
std::vector<std::unique_ptr<T>> vec;
vec.insert(vec.begin(), make_unique<T>());
which uses a standard smart pointer and makes the smart pointer creation explicit.
I have a vector of vectors and I wish to delete myvec[i] from memory entirely, free up the room, and so on. Will .erase or .clear do the job for me? If not, what should I do?
Completely Removing The Vector
If you want to completely remove the vector at index i in your myvec, so that myvec[i] will no longer exist and myvec.size() will be one less that it was before, you should do this:
myvec.erase (myvec.begin() + i); // Note that this only works on vectors
This will completely deallocate all memories owned by myvec[i] and will move all the elements after it (myvec[i + 1], myvec[i + 2], etc.) one place back so that myvec will have one less vector in it.
Emptying But Keeping The Vector
However, if you don't want to remove the ith vector from myvec, and you just want to completely empty it while keeping the empty vector in place, there are several methods you can use.
Basic Method
One technique that is commonly used is to swap the vector you want to empty out with a new and completely empty vector, like this:
// suppose the type of your vectors is vector<int>
vector<int>().swap (myvec[i]);
This is guaranteed to free up all the memory in myvec[i], it's fast and it doesn't allocate any new heap memory or anything.
This is used because the method clear does not offer such a guarantee. If you clear the vector, it always does set its size to zero and destruct all the elements, but it might not (depending on the implementation) actually free the memory.
In C++11, you can do what you want with two function calls: (thanks for the helpful comment)
myvec[i].clear();
myvec[i].shrink_to_fit();
Generalization
You can write a small function that would work for most (probably all) STL containers and more:
template <typename T>
void Eviscerate (T & x)
{
T().swap (x);
}
which you use like this:
Eviscerate (myvec[i]);
This is obviously cleaner and more readable, not to mention more general.
In C++11, you can also use decltype to write a generic solution (independent of the type of your container and elements,) but it's very ugly and I only put it here for completeness:
// You should include <utility> for std::remove_reference
typename std::remove_reference<decltype(myvec[i])>::type().swap(myvec[i]);
My recommended method is the Eviscerate function above.
myvec.erase( myvec.begin() + i ) will remove myvec[i]
completely, calling its destructor, and freeing all of its
dynamically allocated memory. It will not reduce the memory
used directly by myvec: myvec.size() will be reduced by one,
but myvec.capacity() will be unchanged. To remove this last
residue, C++11 has myvec.shrink_to_fit(), which might remove
it; otherwise, you'll have to make a complete copy of myvec,
then swap it in:
void
shrink_to_fit( MyVecType& target )
{
MyVecType tmp( target.begin(), target.end() );
target.swap( tmp );
}
(This is basically what shring_to_fit will do under the hood.)
This is a very expensive operation, for very little real gain,
at least with regards to the removal of single elements; if you
are erasing a large number of elements, it might be worth
considering it after all of the erasures.
Finally, if you want to erase all of the elements,
myvec.clear() is exactly the same as myvec.erase() on each
element, with the same considerations described above. In this
case, creating an empty vector and swapping is a better
solution.
This question already has answers here:
Copying std::vector: prefer assignment or std::copy?
(6 answers)
Closed 2 years ago.
I am trying to efficiently make a copy of a vector. I see two possible approaches:
std::vector<int> copyVecFast1(const std::vector<int>& original)
{
std::vector<int> newVec;
newVec.reserve(original.size());
std::copy(original.begin(), original.end(), std::back_inserter(newVec));
return newVec;
}
std::vector<int> copyVecFast2(std::vector<int>& original)
{
std::vector<int> newVec;
newVec.swap(original);
return newVec;
}
Which of these is preferred, and why? I am looking for the most efficient solution that will avoid unnecessary copying.
They aren't the same though, are they? One is a copy, the other is a swap. Hence the function names.
My favourite is:
a = b;
Where a and b are vectors.
Your second example does not work if you send the argument by reference. Did you mean
void copyVecFast(vec<int> original) // no reference
{
vector<int> new_;
new_.swap(original);
}
That would work, but an easier way is
vector<int> new_(original);
This is another valid way to make a copy of a vector, just use its constructor:
std::vector<int> newvector(oldvector);
This is even simpler than using std::copy to walk the entire vector from start to finish to std::back_insert them into the new vector.
That being said, your .swap() one is not a copy, instead it swaps the two vectors. You would modify the original to not contain anything anymore! Which is not a copy.
Direct answer:
Use a = operator
We can use the public member function std::vector::operator= of the container std::vector for assigning values from a vector to another.
Use a constructor function
Besides, a constructor function also makes sense. A constructor function with another vector as parameter(e.g. x) constructs a container with a copy of each of the elements in x , in the same order.
Caution:
Do not use std::vector::swap
std::vector::swap is not copying a vector to another, it is actually swapping elements of two vectors, just as its name suggests. In other words, the source vector to copy from is modified after std::vector::swap is called, which is probably not what you are expected.
Deep or shallow copy?
If the elements in the source vector are pointers to other data, then a deep copy is wanted sometimes.
According to wikipedia:
A deep copy, meaning that fields are dereferenced: rather than references to objects being copied, new copy objects are created for any referenced objects, and references to these placed in B.
Actually, there is no currently a built-in way in C++ to do a deep copy. All of the ways mentioned above are shallow. If a deep copy is necessary, you can traverse a vector and make copy of the references manually. Alternatively, an iterator can be considered for traversing. Discussion on iterator is beyond this question.
References
The page of std::vector on cplusplus.com
new_vector.assign(old_vector.begin(),old_vector.end()); // Method 1
new_vector = old_vector; // Method 2
you should not use swap to copy vectors, it would change the "original" vector.
pass the original as a parameter to the new instead.
It's been a while since I programmed in C++, and after coming from python, I feel soooo in a straight jacket, ok I'm not gonna rant.
I have a couple of functions that act as "pipes", accepting a list as input, returning another list as output (based on the input),
this is in concept, but in practice, I'm using std::vector to represent the list, is that acceptable?
further more, I'm not using any pointers, so I'm using std::vector<SomeType> the_list(some_size); as the variable, and returning it directly, i.e. return the_list;
P.S. So far it's all ok, the project size is small and this doesn't seem to affect performance, but I still want to get some input/advice on this, because I feel like I'm writing python in C++.
The only thing I can see is that your forcing a copy of the list you return. It would be more efficient to do something like:
void DoSomething(const std::vector<SomeType>& in, std::vector<SomeType>& out)
{
...
// no need to return anything, just modify out
}
Because you pass in the list you want to return, you avoid the extra copy.
Edit: This is an old reply. If you can use a modern C++ compiler with move semantics, you don't need to worry about this. Of course, this answer still applies if the object you are returning DOES NOT have move semantics.
If you really need a new list, I would simply return it. Return value optimization will take care of no needless copies in most cases, and your code stays very clear.
That being said, taking lists and returning other lists is indeed python programming in C++.
A, for C++, more suitable paradigm would be to create functions that take a range of iterators and alter the underlying collection.
e.g.
void DoSomething(iterator const & from, iterator const & to);
(with iterator possibly being a template, depending on your needs)
Chaining operations is then a matter of calling consecutive methods on begin(), end().
If you don't want to alter the input, you'd make a copy yourself first.
std::vector theOutput(inputVector);
This all comes from the C++ "don't pay for what you don't need" philosophy, you'd only create copies where you actually want to keep the originals.
I'd use the generic approach:
template <typename InIt, typename OutIt>
void DoMagic(InIt first, InIt last, OutIt out)
{
for(; first != last; ++first) {
if(IsCorrectIngredient(*first)) {
*out = DoMoreMagic(*first);
++out;
}
}
}
Now you can call it
std::vector<MagicIngredients> ingredients;
std::vector<MagicResults> result;
DoMagic(ingredients.begin(), ingredients.end(), std::back_inserter(results));
You can easily change containers used without changing the algorithm used, also it is efficient there's no overhead in returning containers.
If you want to be really hardcore, you could use boost::tuple.
tuple<int, int, double> add_multiply_divide(int a, int b) {
return make_tuple(a+b, a*b, double(a)/double(b));
}
But since it seems all your objects are of a single, non-polymorphic type, then the std::vector is all well and fine.
If your types were polymorphic (inherited classes of a base class) then you'd need a vector of pointers, and you'd need to remember to delete all the allocated objects before throwing away your vector.
Using a std::vector is the preferably way in many situations. Its guaranteed to use consecutive memory and is therefor pleasant for the L1 cache.
You should be aware of what happends when your return type is std::vector. What happens under the hood is that the std::vector is recursive copied, so if SomeType's copy constructor is expensive the "return statement" may be a lengthy and time consuming operation.
If you are searching and inserting a lot in your list you could look at std::set to get logarithmic time complexity instead of linear. (std::vectors insert is constant until its capacity is exceeded).
You are saying that you have many "pipe functions"... sounds like an excellent scenario for std::transform.
Another problem with returning a list of objects (opposed to working on one or two lists in place, as BigSandwich pointed out), is if your objects have complex copy constructors, those will called for each element in the container.
If you have 1000 objects each referencing a hunk of memory, and they copy that memory on Object a, b; a=b; that's 1000 memcopys for you, just for returning them contained in a container. If you still want to return a container directly, think about pointers in this case.
It works very simple.
list<int> foo(void)
{
list<int> l;
// do something
return l;
}
Now receiving data:
list<int> lst=foo();
Is fully optimal because compiler know to optimize constructor of lst well. and
would not cause copies.
Other method, more portable:
list<int> lst;
// do anything you want with list
lst.swap(foo());
What happens: foo already optimized so there is no problem to return the value. When
you call swap you set value of lst to new, and thus do not copy it. Now old value
of lst is "swapped" and destructed.
This is the efficient way to do the job.