3 ms·
> The whole point of move constructors are observable side-effects. Nonsense. > Furthermore move constructors often have to throw an exception due to the fact
by nly 11y ago
> The whole point of move constructors are observable side-effects.
Nonsense.
> Furthermore move constructors often have to throw an exception due to the fact that moving an object should leave the original object in a valid state.
Whether or not move constructors should leave objects in a 'valid state', whatever you mean by that, is hotly contested. Personally I'm of the opinion the only valid operations on a moved-from object should be to move-assign to it (otherwise literally every mutating algorithm is broken) and, obviously, to destroy it.
> Often times leaving the original object in a valid state requires involves performing an operation that could potentially fail.
Which is exactly why I'm of the above opinion. Making move non-throwing is more or less always trivial and cheap, whereas doing so while ensuring a moved-from object has a valid and useful state, where all class invariants have been maintained, can be expensive.
You should definitely favour a noexcept move constructor that results in an unspecified state over a implementing a throwing move. Just don't do it. If your move constructor throws then doing anything useful with your class becomes very expensive (because classes like std::vector will start copying your objects to move them around).
> In the case of std::map and std::list, a conforming implementation may have to allocate memory in order for the original object to be in a valid state.
This is just wrong. Moving a std::list will not throw provided the associated memory allocator is noexcept move constructible (and std::allocator is). The same is true of std::map.
- plorkyeran 11y agostd::list's move constructor is deliberately not specified to be noexcept even when the allocator's is, and in Dinkumware's implementation it actually can throw, since it allocates a new end sentinel for the moved-from list.
- nly 11y agoConstructors may need to allocate a sentinel, I see no reason for the move constructor to do so. I'd also question the performance benefits of having a sentinel (basically avoiding additional null pointer checks) has on performance given todays relative cache penalties.