While explaining move operations on objects with a colleague, I basically said that move operations should not throw exceptions in a container because if the move operation fails, then there is no way to bring back the original object reliably. Thinking about this more, I'm wondering if that is not correct and that if a move operation that does throw, it could revert the original object back to it's original state.
The reason for this, is that if an object can throw, then it would throw not due to copying or moving the contained objects from the old to the new address, but throw if a resource failed to be acquired. So all of the original information should still be there. If this is the case, then should the compiler not be able to reverse the operations that it did to reconstitute the original object?
It could be possible for an operation to be one way, like moving an integer, but in that case it could just terminate the application, and perhaps if the developer wanted to avoid the one way operation could use a swap method instead.
This would only be possible on default move operators, as if there are any additional logic, it may be difficult for the compiler to do a reverse partial transform.
Am I oversimplifying things? Is there something that I missed which keeps containers from moving objects without a non-throwing move constructor/operator?
noexcept is nice for two reasons: The compiler can optimize a little better because it doesn't need to emit any code for unwinding a call stack in case of an exception, and. It leads to incredible performance differences at runtime for std::vector (and other containers, too)
Which are not full container classes in c++? Explanation: Container adaptors are not full container classes, but classes that provide a specific interface relying on an object of one of the container classes such as deque or list to handle the elements.
In C++, the term memory ownership refers to the entity that is responsible for enforcing the lifetime of a particular memory allocation.
Is an array a container? Arrays hold a set of elements of the same type in a contiguous memory location so, do they not qualify as containers? In most languages, an array would indeed qualify as a container.
You can use types with throwing moves in containers like vector
which can move their elements. However, such containers will not use throwing move operations.
Let's say you have a vector
of 10 throwing move elements. And the vector
needs to resize itself. So it moves 5 objects to the new memory, but the 6th throws. Well, that's OK; construction failed, so the assumption is that the value of the 6th object is fine. That is, whatever that type's exception guarantee is will be how things work.
But then, because the movement of one object failed, vector
needs to move the last 5 objects back to the first array, since vector
is trying to provide a strong exception guarantee. That's a problem, since the move back can itself fail.
C++ in general does not have valid answers when the process of repairing a failure itself fails. You can see that in exceptions; you can't emit an exception from a destructor that is called during the process of unwinding due to an exception failure. std::terminate
happens in this case.
The same goes for vector
. If the move back were to fail, vector
has no sane answer. As such, if vector
cannot guarantee that restoring its previous array state is noexcept
, then it will use copying, since that can provide that guarantee.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With