12

In my code, I have something like this:

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

As you can see, I'm using std::move on an object of type deduced to unordered_map<string, string>&, which is obviously not unordered_map<string, string>&&. Still, I know for sure that because rawEntities goes out of scope after the for loop, its elements (the string->string maps) will never be used again. So I'm figuring that it's safe to steal (move) its elements data because they won't be used again.

When I run the program, it seems to work. But is this bad practice / an anti-pattern, and particularly, does the standard guarantee it is safe?

bombax
  • 1,189
  • 8
  • 26
  • Just looking at your question title, the answer is that temporary objects are (by definition) prvalues, and `std::move` is just a cast, which is unnecessary in that case. – Kerrek SB Aug 26 '15 at 21:03

2 Answers2

17

On the contrary. Using std::move on temporary objects is pointless. They're already R-values, and will be deduced as R-value references when passed to functions. The whole point of std::move is to turn L-values into R-value references so they can be moved from.

So I'm figuring that it's safe to steal (move) its elements data because they won't be used again.

Yes, this is correct.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
4

In general, temporary objects are unnamed and are already rvalues. std::move isn't really applicable, since it is unnamed.

When is std::move applicable? Whenever the object is going to expire and would no longer be required. This is what std::move does, it casts the value category such that it can be moved from.

It is something of an interesting use case - stealing the (filtered) contents of a container and not just the entire container.

Given the contents of the vector are not going to be required after the for loop completes, then yes, it would work as expected.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Niall
  • 30,036
  • 10
  • 99
  • 142