NicolBolas already gave a pretty clear answer, but since there appears to be some confusion in the comments regarding the "static storage duration" which I feels needs some clarity.
The function called new_delete_resource()
is defined, on cppreference, to have the following affect:
Return Value:
Returns a pointer p to a static storage duration object of a type derived from std::pmr::memory_resource
, with the following properties:
- its
allocate()
function uses ::operator new
to allocate memory;
- its
deallocate()
function uses ::operator delete
to deallocate memory;
- for any
memory_resource
r
, p->is_equal(r)
returns &r == p
.
The same value is returned every time this function is called.
(Emphasis mine)
What this means is that the std::pmr::memory_resource
object returned from this function has static-storage duration; not that calls of allocate()
operate on static storage duration.
For example, this may be implemented as:
namespace std::pmr {
memory_resource* new_delete_resource() {
static internal_new_delete_resource s_new_delete_resource;
return &s_new_delete_resource;
}
} // namespace std::pmr
To be clear: the following code does not allocate memory with static-storage duration (by default[1]):
auto* p = new_delete_resource()->allocate(...);
Rather, the above code is actually roughly equivalent to writing:
auto* p = new char[...];
The "global operators" that the documentation refers to are the functions ::operator new
and ::operator delete
.
[1] By default, these operate on the heap -- though ::operator new
and ::operator delete
can be overridden by the user if they choose to define these. A program is legally allowed to define their own allocation mechanism if they choose -- at which point this may, in fact, be static-storage duration. However, such a point is more esoteric; as far as the standard is concerned, the storage duration of the pointer is dynamic -- and not explicitly static storage.
So what's the point?
Aside from being a suitable and useful default for an allocator (e.g. the default_resource
), this also offers great composability with other memory_resource
s. For example, a pool_resource
may use this as the upstream memory_resource
for when the pool runs out of allocations.
Having a resource like this becomes really important for symmetry with std::allocator<T>
(which means a cheap upgrade path), and for enabling std::pmr::polymorphic_allocator
to have a suitable default.
Why new
and delete
?
new
and delete
are built-in facilities in C++ -- so it's easy to use these and base it in terms of this. Since the global ::operator new
and ::operator delete
can be overridden by custom definitions, this makes it a simple customization point that works seamlessly in any existing application. Additionally, it follows the existing pattern for std::allocator<T>
which used new
and delete
.
If, instead, this were std::malloc
/std::free
, or some other allocation function -- then old user code that previously defined custom hooks for ::operator new
would cease to function correctly. This would lead the behavior of a container using std::allocator<T>
to behave differently than a container using std::pmr::polymorphic_allocator<T>
with a std::pmr::new_delete_resource
-- which would be undesirable. (Note: the default resource is a new_delete_resource
, which is what provides this symmetry by default).