Is it okay to "Move" an object from a queue, if you're about to pop from it?

Xirema picture Xirema · May 11, 2016 · Viewed 9.4k times · Source

I've been working on a parser for commands (which are fancy wrappers around large arrays of data), and have a queue that unhandled commands reside on. If I need a command, I query it with code like this:

boost::optional<command> get_command() {
    if (!has_command()) return boost::optional<command>(nullptr);
    else {
        boost::optional<command> comm(command_feed.front()); //command_feed is declared as a std::queue<command>
        command_feed.pop();
        return comm;
    }
}

The problem is, these commands could be megabytes in size, under the right circumstances, and need to parse pretty quickly. My thought was that I could optimize the transferal to a move like so:

boost::optional<command> get_command() {
    if (!has_command()) return boost::optional<command>(nullptr);
    else {
        boost::optional<command> comm(std::move(command_feed.front())); //command_feed is declared as a std::queue<command>
        command_feed.pop();
        return comm;
    }
}

And it seems to work for this specific case, but can this be used as a general purpose solution to any properly maintained RAII object, or should I be doing something else?

Answer

Barry picture Barry · May 11, 2016

Yes, this is perfectly safe:

std::queue<T> q;
// add stuff...

T top = std::move(q.front());
q.pop();

pop() doesn't have any preconditions on the first element in the q having a specified state, and since you're not subsequently using q.front() you don't have to deal with that object being invalidated any more.

Sounds like a good idea to do!