The idiomatic way to implement move-operations on classes with a standard container member can not be noexcept
and therefore will not be movable by operations like vector.push_back()
. Or am I mistaken?
To get speed from
vector<Elem> data;
// ...
data.push_back( elem );
We are encouraged to make out move operations noexcept
-- so during the vectors resize the library can safely move elements to the reallocated storage.
class Elem {
// ...
Elem(Elem&&) noexcept; // noexcept important for move
Elem& operator=(Elem&&) noexcept; // noexcept important for move
};
So far so good, now my elem
s can be pushed-back much faster.
But: If I add a container as member, can my class be still be marked noexcept-move? All standard containers do not have their move noexcept
!
class Stuff {
vector<int> bulk;
// ...
Stuff(Stuff&& o) // !!! no noexcept because of vector-move
: bulk(move(o.bulk))
{}
Stuff& operator=(Stuff&&) // !!! no noexcept...
{ /* appropriate implementation */ }
};
This also means, that we can also not rely on the compiler-generated move-operations, right? The following complete class will also not have noexcept
-move-operations and therefore not be "fast", correct?
struct Holder {
vector<int> bulk;
};
Maybe vector<int>
is a bit too simple to move, but what about vector<Elem>
?
This would have great consequences on all data structures with containers as members.