C++11: безопасно ли использовать std:: move только для временных объектов?


В моем коде есть что-то вроде этого:

unordered_multimap<string, unordered_map<string, string> > mEntities;
...
vector<unordered_map<string, string> > rawEntities;
if (qi::phrase_parse(&buf[0], (&buf[0]) + buf.size(), EntityParser<char*>(), qi::space, rawEntities)) {
    for (auto &propGroup : rawEntities) {
        auto search = propGroup.find("classname");
        if (search != propGroup.end()) {
            // is stealing propGroup safe???
            mEntities.emplace(search->second, std::move(propGroup)); 
        }
    }
}
// rawEntities goes out of scope here
Как вы можете видеть, я использую std::move для объекта типа, выведенного в unordered_map<string, string>&, который, очевидно, не является unordered_map<string, string>&&. Тем не менее, я точно знаю, что поскольку rawEntities выходит из области действия после цикла for, его элементы (string->string maps) никогда больше не будут использоваться. Поэтому я считаю, что безопасно красть (перемещать) данные его элементов, потому что они больше не будут использоваться.

Когда я запускаю программу, она, кажется, работает. Но разве это плохая практика / an анти-паттерн, и в частности, гарантирует ли стандарт его безопасность?

2 8

2 ответа:

Наоборот. Использование std::move на временных объектах бессмысленно. Они уже являются R-значениями и будут выведены как ссылки на R-значения при передаче функций. Весь смысл std::move состоит в том, чтобы превратить L-значения в ссылки на R-значения, чтобы их можно было перемещать.

Итак, я полагаю, что безопасно красть (перемещать) данные его элементов потому что они больше не будут использоваться.

Да, это верно.

В общем случае, временные объекты безымянны и уже являются rvalues . std::move на самом деле неприменим, так как он не имеет имени.

Когда std::move применимо? Всякий раз, когда объект истекает и больше не требуется. Это то, что делает std::move, он отбрасывает категорию значения так,чтобы ее можно было переместить.

Это что - то вроде интересного случая использования-кража (фильтрованного) содержимого контейнера, а не только всего контейнера.

Учитывая содержание из vector не будет требоваться после завершения цикла for, тогда да, он будет работать, как ожидалось.