![]() |
Home | Libraries | People | FAQ | More |
Boost.Intrusive containers have no copy
constructor and no copy assignment. A value can be linked to only one container
through each hook, and a container can not create new values, so a copy of
a container can not contain the same values as the source. To copy a container,
use clone_from (see Cloning Boost.Intrusive containers).
The move constructor links the nodes of the source container to the new container:
list
and slist swapped them
in the move assignment. Now all containers move them, with the same requirement
and with noexcept conditions
that check these moves.
rehash with a
new bucket array before you insert values in it.
noexcept
if the copies of the predicates and the moves of the value and bucket
traits are noexcept.
From Boost 1.93, the move assignment a
= boost::move(b)
does these steps:
a are unlinked,
as with a.clear().
The values are not destroyed: the user still owns them.
b are
copied to a. b keeps its predicates.
b
are moved to a. b keeps value traits equal to the ones
of a, as after a move
construction.
b are linked
to a, in the same order.
b is left empty and it
can be used again.
a
takes the bucket array of b
and no longer uses its own bucket array. b
is left without a bucket array, as after a move construction.
a and b are the same object, there are no
effects.
noexcept
if the copies of the predicates and the moves of the value and bucket
traits are noexcept.
This is the behavior of standard containers, where the previous elements
of the target are destroyed and the source container does not receive them.
An intrusive container does not own its values, so it unlinks them instead
of destroying them. Other intrusive container libraries do the same: for
example, the move assignment of LLVM's simple_ilist
unlinks the values of the target and then splices the values of the source.
![]() |
Important |
|---|---|
Before Boost 1.93, the move assignment was equivalent to |
For backwards compatibility, define the macro BOOST_INTRUSIVE_MOVE_ASSIGNMENT_SWAPS
to get the behavior before Boost 1.93. Then the move assignment of all
Boost.Intrusive containers is equivalent
to swap and it is not
noexcept. Define the macro
before you include any Boost.Intrusive
header, with the same value in all the translation units of the program
(for example, in the build system), or the program violates the One Definition
Rule. The macro does not change the containers of Boost.Container,
which use Boost.Intrusive internally.
![]() |
Warning |
|---|---|
|
#define BOOST_INTRUSIVE_MOVE_ASSIGNMENT_SWAPS #include <boost/intrusive/list.hpp> //... a = boost::move(b); //Same as a.swap(b): b now contains the values of a
a.swap(b) and swap(a,
b)
exchange the contents of two containers of the same type:
a and
b are exchanged. No value
is copied, moved or destroyed: only the links change.
swap
call: a swap function
found with argument-dependent lookup, or otherwise the move constructor
and the move assignment.
slist
without the linear<>
or cache_last<>
options: its swap is linear in the number of elements of both lists.
Exception guarantees:
list and slist: the swap does not throw.
set,
multiset, rbtree, and the AVL, splay, scapegoat
and binary search tree variants): the comparison objects are swapped
first. If that swap throws and has no effects, the containers are not
changed.
treap containers (comparison
and priority) and unordered containers (hash and equality) swap two predicates,
one after the other. The swaps of these predicates must not throw: if
the second swap throws, the first predicates are already exchanged and
the containers can not be used.
Iterators and references:
Swap and move assignment are different operations from Boost 1.93: after
a.swap(b), b
contains the previous values of a.
After a =
boost::move(b), the previous values of a
are unlinked and b is empty
(see Move
assignment). Use swap
when both containers must keep their values.