Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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...

like image 723
cfa45ca55111016ee9269f0a52e771 Avatar asked Dec 18 '12 17:12

cfa45ca55111016ee9269f0a52e771


People also ask

What does Splice do in list C++?

The list::splice() is a built-in function in C++ STL which is used to transfer elements from one list to another. The splice() function can be used in three ways: Transfer all the elements of list x into another list at some position. Transfer only the element pointed by i from list x into the list at some position.

Is std::list a linked list?

std::list is a container that supports constant time insertion and removal of elements from anywhere in the container. Fast random access is not supported. It is usually implemented as a doubly-linked list.

How is std::list implemented?

The std::list is implemented as a doubly-linked list. This means list data can be accessed bi-directionally and sequentially.

What is the difference between vector and list in C++?

In vector, each element only requires the space for itself only. In list, each element requires extra space for the node which holds the element, including pointers to the next and previous elements in the list. Insertion at the end requires constant time but insertion elsewhere is costly.


2 Answers

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.

like image 140
Joseph Mansfield Avatar answered Oct 19 '22 22:10

Joseph Mansfield


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 '&&'
}
like image 41
Kerrek SB Avatar answered Oct 19 '22 23:10

Kerrek SB