Search code examples
c++c++11bad-alloc

New throws bad_alloc despite <new> header not being defined?


How is it that a new expression in a program can throw a bad_alloc error despite there being no #include <new> (since this error is defined in the <new> header)?

From 3.7.4. of N3337:

The library provides default definitions for the global allocation and deallocation functions. Some global allocation and deallocation functions are replaceable (18.6.1). A C++ program shall provide at most one definition of a replaceable allocation or deallocation function. Any such function definition replaces the default version provided in the library (17.6.4.6). The following allocation and deallocation functions (18.6) are implicitly declared in global scope in each translation unit of a program.

void* operator new(std::size_t);

void* operator new[](std::size_t);

void operator delete(void*);

void operator delete[](void*);

These implicit declarations introduce only the function names operator new, operator new[], operator delete, and operator delete[]. [ Note: The implicit declarations do not introduce the names std, std::size_t, or any other names that the library uses to declare these names. Thus, a new-expression, delete-expression or function call that refers to one of these functions without including the header <new> is well-formed. However, referring to std or std::size_t is ill-formed unless the name has been declared by including the appropriate header. —end note ] Allocation and/or deallocation functions can also be declared and defined for any class

This still isn't clear to me. The implicit declarations use std::size_t but do not introduce them (and the same must be the case for bad_alloc)? And std::size_t doesn't need to be introduced before a new expression can be used? Can any sense be made of how this is, or do I have to take it at face value?


Solution

  • Your quote says that those global functions exist and are implicitly declared as described. Thus when you invoke new, the global function in the standard library is called. The implementation of the global function new is the one throwing std::bad_alloc, and that implementation had access to <new> at the time of compilation, thus knows how to throw an std::bad_alloc. Your code doesn't need to know what a std::bad_alloc is, unless you're trying to catch it. But other than catching it, this is like you calling any other function from some other library that may be throwing some arbitrary exception. You don't need to know about the details of that exception unless you're trying to catch it, but that doesn't stop the callee from being able to throw it.