在现代 C++ 编程中,高效且灵活的内存管理一直是追求的重要目标之一。 在 C++17 标准中,引入了 std::pmr::memory_resource 和 std::polymorphic_allocator 这两个强大的组件,它们为分配内存提供了高度的灵活性和可扩展性,使你可根据不同应用场景和需求,更加精细地控制内存的分配和释放过程。 以下是对这两个组件的详细解析。
一、std::pmr::memory_resource
(一) 基本概念
std::pmr::memory_resource 是一个定义了一套标准的分配内存接口的抽象基类。 该接口为用户统一处理不同分配内存策略,允许用户根据具体需求自定义分配内存,如线程本地分配内存、内存池分配等。
使用该抽象基类,可统一管理和使用不同分配内存器,提高了代码的可维护性和可扩展性。
(二) 主要成员函数
1. allocate(std::size_t bytes)
功能:该函数用来分配指定字节数的内存。在实际应用中,它会根据具体的分配内存策略来找合适的内存块,并把它分配给调用者。
参数:bytes 参数表示要分配的字节数。该参数是调用者根据自身需求传入的,它决定了要分配的内存大小。 返回值:函数返回分配的内存的指针。调用者可用该指针来访问和操作分配的内存。
2. deallocate(void* ptr, std::size_t bytes)
功能:此函数用来释放指定指针指向的内存。当调用者不再使用之前分配的内存时,就可调用该函数来释放该内存,这样其他程序可使用它。
参数:ptr 是要释放的内存的指针,指向之前分配函数分配的内存块的开始位置。bytes 是该内存块的大小,用来帮助分配内存器正确地释放内存。
注意:在调用释放函数时,需要确保传入的指针和大小与之前分配函数返回的指针和分配的大小一致,否则可能会泄漏内存或有其他未定义行为。
3. is_equal(const memory_resource& other) const noexcept
功能:该函数用来判断当前内存资源是否与另一个内存资源相等。这里的相等一般表示两个内存资源可互相替代使用,即它们的分配和释放内存行为是兼容的。
参数:other 是与当前内存资源比较的另一个内存资源对象。 返回值:如果两个内存资源相等,则返回真,否则返回假。该函数有时非常有用,如在需要判断两个不同容器是否使用相同内存资源时。
(三) 使用场景
1. 分配内存的灵活性
在不同应用场景中,可能需要不同分配内存策略。如,在多线程环境中,为了避免线程间的竞争和提高性能,可用线程本地分配内存策略。 std::pmr::memory_resource 允许用户根据这些不同需求自定义分配内存策略,从而提高程序的效率和效率。
2. 管理资源的统一性
在大型项目中,可用多种不同分配器,会导致不同分配器间的冲突和管理困难。std::pmr::memory_resource 提供的统一接口,可统一管理这些不同分配器,避免冲突,提高代码的可维护性。
二、std::polymorphic_allocator
(一) 基本概念
std::polymorphic_allocator 是一个多态分配器,它允许用户指定不同 std::pmr::memory_resource 对象来分配内存。
它是一个 T 模板参数表示分配器分配的元素类型的模板类。即 std::polymorphic_allocator 可按需分配不同类型的元素,且可用不同内存资源来分配。
(二) 主要成员函数
1. allocate(std::size_t n)
功能:该函数用来分配 n 个元素的内存。它会调用关联的 std::pmr::memory_resource 对象的分配函数来实际分配内存。 参数:n 表示要分配的元素数量。该参数决定了会根据 T 元素类型的大小计算的要分配的内存大小。 返回值:返回指向分配的第一个元素的位置的分配的内存的指针。
2. deallocate(T* ptr, std::size_t n)
功能:此函数用来释放指定指针指向的内存。它会调用关联的 std::pmr::memory_resource 对象的释放函数来实际释放内存。
参数:ptr 是指向之前分配函数分配的内存块的开始位置的要释放的内存的指针。n 是该内存块中用来帮助内存资源正确地释放内存的元素数。

