std::list::splice, list&& VS list&

Some methods of std::list, and probably other STL containers, have a new overload added in C++11. The one I need is list::splice(). One method takes a list& parameter, the other one takes a list&& parameters.

I'd like to know what the difference, and which ine I should prefer.

I looked at the implementation of libstdc++ (the standard C++ library used by the GCC compiler) and it uses the list&& version in both cases internally. Also the C++11 specification says nothing about this issue. It just offers 2 methods without explaining the difference.

You don't move the list itself, and you don't move the nodes (copying their pointers seems like the way to move nodes from one list to another), so why does it matter? I have just one idea, maybe using list&& is like a promise to the compiler you don't need the other list anymore and the the compiler can save a few operations because it doesn't have to keep the other list valid...

Upvotes: 5

Views: 676

Answers (2)

Joseph Mansfield
Joseph Mansfield

Reputation: 110658

You shouldn't need to care very much. The overload with the std::list&& parameter will be chosen when the argument you pass is an rvalue - usually when the object it refers to is a temporary. You don't need to explicitly say which overload you want to use.

The reason these two versions of the function exist is for convenience, so that the client doesn't have to create a temp std::list variable from the temporary object before passing it to splice (thanks to @HowardHinnent in the comments).

Also, when the list you're splicing from is a temporary object, there's no point caring about maintaining its state. The && version of the function may just rip the guts from that list, leaving a mess all over the floor. This might be done for efficiency (but actually, std::list doesn't have much reason to).

If you have a std::list, other, that you know you'll never use again, you can voluntarily say "I don't care what you do with it", by using std::move:

l.splice(pos, std::move(other));

The expression std::move(other) is an rvalue, so the splice function will treat it as though it were a temporary.

Upvotes: 5

Kerrek SB
Kerrek SB

Reputation: 477010

Lvalue references bind to lvalues, and rvalue references to rvalues:

tyedef std::list<Foo> lt;

lt make_list();

int main()
{
    lt x;

    lt tmp = make_list();

    x.splice(tmp);         // needs '&'
    x.splice(make_list()); // needs '&&'
}

Upvotes: 2

Related Questions