8

If I construct an empty std::vector using the default constructor (and the default allocator), can it throw an exception?

In general, allocating space for the elements of a container can throw an exception (which would be a std::bad_alloc). But the default constructor of a std::vector does not need to allocate any such space; it can lazily allocate some space on the first insertion or assignment. But does the C++ standard require that it does not throw exceptions (implying lazy allocation, or catching std::bad_alloc and then falling back to lazy allocation)?

Raedwald
  • 46,613
  • 43
  • 151
  • 237
  • 1
    There is a [related question about `std::list`](https://stackoverflow.com/questions/19930011/can-the-default-constructor-of-stdlistint-throw). – Raedwald May 16 '18 at 09:30

1 Answers1

15

It depends on the default constructor of Allocator. The default constructor of std::vector is declared as

vector() noexcept(noexcept(Allocator())); (since C++17)

And if std::allocator is used then it's noexcept(true); i.e. won't throw exceptions.

allocator() noexcept; (since C++11)

Hence, before C++17, or if using a non-default allocator, throwing exceptions is possible.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • That does not make sense to me, at least, in 'normal' implementations, the default allocator for std::vector could run out of heap memory and throw, right? The only way the vector constructor can be noexcept is if the allocator is noexcept. What am I missing? – Erik Alapää May 16 '18 at 09:38
  • @ErikAlapää You missed nothing. Yes it depends on the `Allocator`; and if `std::allocator` is used then it won't throw for default construction; which is guaranteed. – songyuanyao May 16 '18 at 09:41
  • Although *explicitly* required to be `noexcept` only from C++17, is it implicitly `noexcept` in earlier C++ versions? – Raedwald May 16 '18 at 09:45
  • 6
    Before C++17, the default constructor of vector didn't have a throw specification, which means it was permitted to throw. Same for the standard allocator. Practically, if the default constructor didn't actually allocate, it wouldn't throw - and that has always been a common implementation choice, even if not specifically required. – Peter May 16 '18 at 09:51