Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++11 move insertion for std::deque or std::list

I understand reasonably well how rvalue references work, but I'm not exactly sure how they work with iterators in the STL. Here's something that I want:

void insertList(std::list<int>& L, std::list<int>&& R, std::list<int>::iterator insertPoint)
{
    L.insert(insertPoint, R.begin(), R.end()); // want to use move semantics
}

Now I know that std::list has a splice method. But I want to know if this can work at all. Can it work for deque too?

like image 621
rlbond Avatar asked Sep 27 '12 21:09

rlbond


2 Answers

The splice and moving the contents of the containers are different operations. In the case of splice (which cannot be done with deque) the whole node is transferred from one container to the other. The nodes will no longer be in the original container, and no allocations will be performed by the operation.

The alternative of moving the contents with an algorithm similar to the one you stated, but using a move iterator:

L.insert(insertPoint, 
         std::make_move_iterator(R.begin()), 
         std::make_move_iterator(R.end()));

This will work for both list and deque but the semantics are different. The insertion to the new list will require the allocation of std::distance(R.begin(),R.end()) nodes, the contents of which will be filled by moving from the original container. That reduces the cost of the creation of the new nodes, but they need to be allocated nonetheless. Note that the old list will still contain all the nodes, although they will be empty as the contents of the data have been moved.

In the case of std::list you should prefer splice, but that is not available on other containers. For other containers you will be left with the approach above, where the cost of building the container data structure has to be taken, although the cost of the creation of the stored data can be avoided.

like image 104
David Rodríguez - dribeas Avatar answered Oct 07 '22 01:10

David Rodríguez - dribeas


You want std::make_move_iterator():

L.insert(
    insertPoint,
    std::make_move_iterator(R.begin()),
    std::make_move_iterator(R.end())
);
like image 34
ildjarn Avatar answered Oct 07 '22 01:10

ildjarn