Подтвердить что ты не робот

Могу ли я перенести назначение std:: map в другую std:: map?

Можно ли вставить содержимое временной std:: map temp в другую std:: map m с помощью семантики перемещения, чтобы значения из временных не были скопированы и повторно использованы?

Пусть говорят:

std::map<int, Data> temp;
std::map<int, Data> m;

Один из способов копирования значений из temp в m:

m.insert(temp.begin(),temp.end());

Как переместить элементы temp в m вместо копирования?

4b9b3361

Ответ 1

СОВЕТ: Прочитайте обновление сначала!

Текущий стандарт С++ 11 и черновик С++ 14 не предоставляют функцию-член, чтобы включить эту функцию. Поскольку lavr предложил, вы все еще можете написать

m.insert(make_move_iterator(begin(temp)),
         make_move_iterator(end  (temp)));

который перемещает значения из исходного контейнера в контейнер назначения. Однако ни контейнерные узлы, ни клавиши не будут перемещены. Для этого требуются выделения памяти (по крайней мере, для создания новых узлов на карте назначения). Количество элементов в исходном контейнере останется неизменным. Причина копирования проста: Тип значения std::map - std::pair<const Key,T>. И переход от const Key по сути копирует ключ (если только кто-то не перегружает конструктор Key, который принимает const Key &&, для которого я не могу думать об адекватной причине).

Если вам нужно переместить данные из одного контейнера в другой, вы можете использовать std::list вместо std::map. У него есть функция member splice, которая перемещает элементы из одного списка в другой в постоянное время.

UPDATE:

Так как С++ 17 существует функция std::map::merge(), которая в основном ставит все элементы одного std::map в другой std::map без перемещения или копирования фактических элементов, но только путем указания внутренних указателей. Он очень похож на std::list::splice(), который существует с С++ 98.

Итак, вы можете написать

m.merge( temp );

для достижения вашей цели. Это более эффективно, чем копирование или перемещение всех элементов из одного контейнера в другой.

Но будьте осторожны! Конфликтные ключи не будут разрешены: для совпадающих ключей ничего не будет сделано.

Ответ 2

Не пробовал, но я думаю std:: move_iterator:

 using it = std::map<int, Data>::iterator;
 using mv = std::move_iterator <it>;

 m.insert(mv(temp.begin()),mv(temp.end()));

Ответ 3

Я не думаю, что это возможно. В других контейнерах я бы предложил адаптер std::move_iterator, но это не работает, потому что ключ карты является константой.

Другими словами, вы не можете перемещать элементы один за другим с карты, потому что это может изменить ключи, которые карта не позволяет.

И нет никакого способа просто переместить с одной карты на другую. Список поддерживает сращивание, но я боюсь, что деревья этого не делают.