Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 284
Xirema Avatar asked May 11 '16 21:05

Xirema


People also ask

Does queue pop return anything?

Since it is impossible for pop() to return a value in such a way as to be both efficient and correct, it is more sensible for it to return no value at all and to require clients to use front() to inspect the value at the front of the queue.

What does Pop do in queue?

C++ Queue Library - pop() Function The C++ function std::queue::pop() removes front element of the queue and reduces size of the queue by one. This member function effectively calls the pop_front member function of the underlying container.

Does queue pop call destructor?

"pop() removes the object from the underlying container, hence calls its destructor (if any)".


2 Answers

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!

like image 189
Barry Avatar answered Oct 06 '22 09:10

Barry


It depends on what the move constructor for your type does. If it leaves the original object in a state that can safely be destroyed, then all is well. If not, then you may be in trouble. Note that the comments about preconditions and valid states are about constraints on types defined in the standard library. Types that you define do not have those constraints, except to the extent that they use types from the standard library. So look at your move constructor to sort out what you can and can't do with a moved-from object.

like image 35
Pete Becker Avatar answered Oct 06 '22 09:10

Pete Becker