A std::list
stores its elements in nodes. When you add an element a new node is allocated, then the element is stored in the node (via a call to std::allocator_traits<A>::construct
, which typically does a placement-new to construct the object in place inside the node), and then finally the node is added to the list, by updating the pointers of the new node and the adjacent node(s) to link it into the list.
If a bad_alloc
exception is thrown it can only be from allocating the new node, or from constructing the element inside the node (because updating the pointers won't throw anything).
If the exception happens when allocating the node object then it is very likely that the object has not been moved from yet, because no attempt has been made to move-construct a new element (you can't do that until you have a node to construct it into!). There's no guarantee that the container doesn't create intermediate variables before constructing the final element inside the node, but that would be a poor quality implementation, as there is no reason to do that.
If the class has a non-throwing move constructor then you know that the exception must have come from the node allocation. Otherwise, if the exception comes from constructing the element then the state of the rvalue argument will be dictated by the exception-safety guarantees of the class in question.
So in short, if the std::list
implementation is bad, or the object being inserted can throw during move construction and doesn't have the strong exception-safety guarantee, then the rvalue argument might be left in a moved-from state. But otherwise, you should be able to rely on it being unmodified.