Classes and class hierarchies
C.66
Make move operations `noexcept`
Reason
A throwing move violates most people's reasonable assumptions. A non-throwing move will be used more efficiently by standard-library and language facilities.
Example
template<typename T>
class Vector {
public:
Vector(Vector&& a) noexcept :elem{a.elem}, sz{a.sz} { a.elem = nullptr; a.sz = 0; }
Vector& operator=(Vector&& a) noexcept {
if (&a != this) {
delete elem;
elem = a.elem; a.elem = nullptr;
sz = a.sz; a.sz = 0;
}
return *this;
}
// ...
private:
T* elem;
int sz;
};
These operations do not throw.
Example, bad
template<typename T>
class Vector2 {
public:
Vector2(Vector2&& a) noexcept { *this = a; } // just use the copy
Vector2& operator=(Vector2&& a) noexcept { *this = a; } // just use the copy
// ...
private:
T* elem;
int sz;
};
This Vector2 is not just inefficient, but since a vector copy requires allocation, it can throw.
Enforcement
(Simple) A move operation should be marked noexcept.