C++11 перемещение вставки для std:: deque или std:: list

Я достаточно хорошо понимаю, как работают ссылки rvalue, но я не совсем уверен, как они работают с итераторами в STL. Вот что я хочу:

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
}

теперь я знаю, что std:: list имеет метод соединения. Но я хочу знать, может ли это вообще сработать. Может это сработать и для дека?

2 ответов


на splice и двигаясь содержимое контейнеров-это различные операции. В случае splice (что невозможно сделать с deque) весь узел переносится из одного контейнера в другой. Узлы больше не будут находиться в исходном контейнере, и никакие распределения не будут выполняться операцией.

альтернатива двигаясь содержимое с алгоритмом, похожим на тот, который вы указали, но с использованием движение итератор:

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

это будет работать для list и deque но семантика разная. Для вставки в новый список потребуется выделение std::distance(R.begin(),R.end()) узлы, содержимое которых будет заполнено путем перемещения из исходного контейнера. Это снижает стоимость создания новых узлов, но тем не менее их необходимо выделить. Обратите внимание, что старый список по-прежнему будет содержать все узлы, хотя они будут пустой as содержимое данных было перемещено.

в случае std::list вы должны предпочесть splice, но это недоступно в других контейнерах. Для других контейнеров вы останетесь с подходом выше, где стоимость построения структуры данных контейнера должна быть взята, хотя затраты на создание сохраненных данных можно избежать.


вы хотите std::make_move_iterator():

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