C++ 标准是否保证动态分配是用 new 完成的?

Does the C++ standard guarantee that dynamic allocations are done with new?

简单的学习题。 C++ 标准中是否指定了 std 类 分配内存的方式?我假设在内部,所有分配都在某个时候转发到 new / new[]。我对容器、std::function 和 lambda 进行的分配特别感兴趣。

标准库容器

标准库容器采用分配器模板参数,用于控制内存的分配方式。默认情况下,他们使用 std::allocator<T>. std::allocator<T> has a member function std::allocator<T>::allocate() 即:

Allocates n * sizeof(T) bytes of uninitialized storage by calling ::operator new(std::size_t)

同样,有一个 std::allocator<T>::deallocate() 函数调用 operator delete(void *)

std::function

std::functionseveral constructors,其中一些允许您指定分配器对象以用于其内部分配。如果您不指定一个,那么它将使用 std::allocator.

Lambdas

我不确定您希望使用 lambda 完成哪些分配。当您声明一个 lambda 时,编译器会在幕后合成一个未命名的仿函数类型,在其 operator() 中实现该 lambda。如果您从本地范围捕获任何变量,这些变量将简单地成为该类型定义的一部分,从而增加 lambda 类型的大小,但不需要任何动态分配;捕获的变量只是 lambda 未命名类型的成员。如果您要将 lambda 分配给 std::function 之类的东西,那么 std::function 可以进行动态分配以适应 lambda 增加的大小。

标准库中的 类 通常是模板,可以使用特定的分配器来满足特殊需要。默认情况下,他们使用标准分配器 (std::allocator),它使用 operator newoperator delete:

20.7.9.1 allocator members [allocator.members]
...

pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);

...
Remark: the storage is obtained by calling ::operator new(std::size_t) (18.6.1), but it is unspecified when or how often this function is called...

void deallocate(pointer p, size_type n);

...
Remarks: Uses ::operator delete(void*, std::size_t) (18.6.1), but it is unspecified when this function is called.

由于性能原因,调用运算符 new 和 delete 时未指定的事实允许实现缓存未使用的内存块。

标准容器接受作为分配器的模板化参数。默认情况下,每个标准容器的分配器都是 std::allocator<T> 类型(例如 std::vector<T> 的默认分配器是 std::allocator<T> 类型)。 std::allocator 使用函数 ::operator new(size_t) 分配原始内存。

典型的新表达式(例如 new Type 形式)的部分工作是调用函数 ::operator new(size_t)。但是,不需要默认分配器来使用这样的新表达式。

分配器接口的一部分是提供一个成员函数construct(pointer p, const_reference val)std::allocate<T> returns new((void *)p) T(val) 的成员函数(有时被描述为放置新表达式)。

不要求非默认分配器(例如程序员提供的分配器类型而不是默认分配器)使用 ::operator new() 或新表达式。