1

If memory allocation fails while moving a object into a std::vector, and bad_alloc is thrown, does std::vector guarantee that the moved from object is unaltered/still valid ?

For example:

std::string str = "Hello, World!";
std::vector<std::string> vec;

vec.emplace_back(std::move(str));
/* Is str still valid and unaltered if the previous line throws? */
Unimportant
  • 2,076
  • 14
  • 19

1 Answers1

7

This is covered in [container.requirements.general]/11.2

if an exception is thrown by a push_­back(), push_­front(), emplace_­back(), or emplace_­front() function, that function has no effects.

So, you will not have a moved from object in the event of an exception.

This only covers if the vector throws. We need to look at [vector.modifiers]/1 to see what happens if the move constructor itself throws:

If an exception is thrown while inserting a single element at the end and T is Cpp17CopyInsertable or is_­nothrow_­move_­constructible_­v<T> is true, there are no effects. Otherwise, if an exception is thrown by the move constructor of a non-Cpp17CopyInsertable T, the effects are unspecified.

emphasis mine

And in that case the behavior is unspecified.


In your case std::string has a noexcpet move constructor so you will have a valid object if an exception throws.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • hm I was under the impression the move ctor wouldn't be used unless it was noexcept (or the impl figured out some other way that no exception would be thrown) – Lightness Races in Orbit Aug 09 '19 at 18:41
  • @LightnessRacesinOrbit That is only when growing the vector. It will always call the move on a push/emplace_back for rvalues. – NathanOliver Aug 09 '19 at 18:42
  • Yeah seems fair for the standard not to know the results there. Only the OP, having written the move ctor, can know the effects of throwing out of it. Not part of the q :D – Lightness Races in Orbit Aug 09 '19 at 18:43