STL vector: Moving all elements of a vector
Using C++11, it's as simple as:
A = std::move(B);
Now A
contains the elements that were previously held by B
, and B
is now empty. This avoids copying: the internal representation is simply moved from B
to A
, so this is an O(1)
solution.
As for C++03, as Prætorian states, you could swap the vectors. There is a specialization of the std::swap
function, which takes std::vector
s as its arguments. This effectively swaps the internal representation, so you end up avoiding creating copies of the elements held by them. This function works in O(1)
complexity as well.
STL vector: Moving all elements of a vector
Using C++11, it's as simple as:
A = std::move(B);
Now A
contains the elements that were previously held by B
, and B
is now empty. This avoids copying: the internal representation is simply moved from B
to A
, so this is an O(1)
solution.
As for C++03, as Prætorian states, you could swap the vectors. There is a specialization of the std::swap
function, which takes std::vector
s as its arguments. This effectively swaps the internal representation, so you end up avoiding creating copies of the elements held by them. This function works in O(1)
complexity as well.
Moving elements from std::vector to another one
The std::move
lets you move the objects, as opposed to copying them, allowing for a potentially faster execution speed. The savings may be even greater when you move a range of values. However, when you do move a range from a container, the container still holds the places that were once occupied by these values.
You need to resize the container manually to remove these placeholders if you want to get rid of them (you don't have to, in case you would prefer reusing these container spots for other elements). One way to do it is to call vector::erase
on the same range that you moved out of the container.
How to Move certain elements of std::vector to a new index within the vector?
The above two examples had issues with different input (noted above). I worked out the algorithm to handle the different cases and it passed my unit tests. It can probably be improved for speed.
template <class CONTAINER_TYPE>
void ChangeRecordOrder( CONTAINER_TYPE IN OUT &values,
uint newIndex,
std::vector<uint> IN const &indexesToMove )
{
// Make a copy of the indexesToMove as we need to do fixups to them in certain cases
std::vector<uint> temporaryIndexes = indexesToMove;
for ( uint i=0; i<temporaryIndexes.size(); i++ )
{
uint indexToMove = temporaryIndexes[i];
if ( indexToMove < newIndex )
{
uint leftIndex = indexToMove;
uint rightIndex = newIndex -1;
uint newFirst = leftIndex + 1;
std::rotate( values.begin() + leftIndex, values.begin() + newFirst, values.begin() + rightIndex +1);
// fix up indexes
for( uint j=i+1; j<temporaryIndexes.size(); j++ )
{
uint &futureIndex = temporaryIndexes[j];
if ( futureIndex > leftIndex && futureIndex <=rightIndex )
--futureIndex;
}
}
else if ( indexToMove > newIndex )
{
uint leftIndex = newIndex;
uint rightIndex = indexToMove;
uint newFirst = indexToMove;
std::rotate( values.begin() + leftIndex, values.begin() + newFirst, values.begin() + rightIndex +1);
// fix up indexes
for( uint j=i+1; j<temporaryIndexes.size(); j++ )
{
uint &futureIndex = temporaryIndexes[j];
if ( futureIndex > leftIndex && futureIndex <=rightIndex )
++futureIndex;
}
++newIndex;
}
}
}
Is there a better way of moving elements in a vector
You could use std::rotate
:
#include <algorithm>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> values{1, 2, 3, 4, 5};
std::rotate(values.begin()+2, values.end()-1, values.end());
for(int i: values)
std::cout << i << " ";
std::cout << "\n";
}
try it
Outputs:1 2 5 3 4
You can probably adjust the iterators used if you need to move an element that isn't at the end.
Moving a vector element to the back of the vector
You can do this with std::rotate
from the standard library. Since this doesn't change the vector size it also won't trigger a reallocation. Your function would look something like this:
template <typename T>
void moveItemToBack(std::vector<T>& v, size_t itemIndex)
{
auto it = v.begin() + itemIndex;
std::rotate(it, it + 1, v.end());
}
Moving an item in a vector
I believe you can use std::rotate
to this end.
vector<T> vec = ...
vector<T>::iterator from = ...
vector<T>::iterator to = ...
if(from < to ) {
rotate(from, from+1, to+1);
} else if (from > to) {
rotate(to, from, from+1);
}
Disclaimer: untested code
By the way, you can get the vector index from iterator easily with eg,
vector<T> vec = ...
vector<T>::iterator it = ...
size_t idx = it - vec.begin();
Related Topics
Crtp -- Accessing Incomplete Type Members
Understanding Gsl::Narrow Implementation
How to Test Whether Class B Is Derived from Template Family of Classes
Boost C++ Regex - How to Get Multiple Matches
C++11: "Narrowing Conversion Inside { }" with Modulus
C++ Template/Ostream Operator Question
What Is the Meaning of This Star (*) Symbol in C++? - Pointer to Member
Sigkill While Allocating Memory in C++
What's the Best Hashing Algorithm to Use on a Stl String When Using Hash_Map
Is Substitution Performed on a Variadic Parameter Pack Type If the Pack Is Empty
Visual Studio 2013 Fatal Error C1041 /Fs
How to Overload Operator==() for a Pointer to the Class
What Changes Introduced in C++14 Can Potentially Break a Program Written in C++11
Why Is Copy Constructor Not Being Called in This Code
How to Detect Negative Numbers as Parsing Errors When Reading Unsigned Integers
Most Efficient Way to Check If All _M128I Components Are 0 [Using <= Sse4.1 Intrinsics]
Why Do Sin(45) and Cos(45) Give Different Results
Any C/C++ Refactoring Tool Based on Libclang? (Even Simplest "Toy Example" )