c++11 动态内存管理-提供关于分配器类型的信息(std::allocator_traits)(三)

发布时间:2023年12月28日

提供关于分配器类型的信息

std::allocator_traits

template< class Alloc >
struct allocator_traits;

(C++11 起)

allocator_traits 类模板提供访问分配器 (Allocator) 各种属性的标准化方式。标准容器和其他标准库组件通过此模板访问分配器,这使得能以任何类类型为分配器,只要用户提供的 allocator_traits 特化实现所有要求的功能。

在分配的存储构造对象

std::allocator_traits<Alloc>::construct

template< class T, class... Args >
static void construct( Alloc& a, T* p, Args&&... args );

(C++11 起)

若可能,则在 p 所指向的分配的未初始化存储构造 T 类型对象,通过调用

a.construct(p, std::forward<Args>(args)...)

若以上不可行(例如无 construct() 成员函数),则调用如下的布置 new

::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)

参数

a-用于构造的分配器
args...-传递给 a.construct() 或布置 new 的参数

返回值

(无)

注意

此函数为标准库容器在插入、复制或移动元素时所用。

因为此函数提供到布置 new 的自动回落,故 C++11 起成员函数 construct()分配器 (Allocator) 的可选要求。

析构存储于已分配存储的对象

std::allocator_traits<Alloc>::destroy

template< class T >
static void destroy( Alloc& a, T* p );

(C++11 起)

调用 p 所指向对象的析构函数。若可能,则通过调用 a.destroy(p) 这么做。若不可能(例如 a 无成员函数 destroy() ),则直接调用 *p 的析构函数,同 p->~T() 。

参数

a-用于析构的分配器
p-指向要被销毁的对象的指针

返回值

(无)

注意

因为此函数提供到析构函数的自动回落,故 C++11 起成员函数 destroy()分配器 (Allocator) 的可选要求。

调用示例

#include <iostream>
#include <memory>

struct Cell
{
    int x;
    int y;

    Cell()
    {
        std::cout << __FUNCTION__;
    }
    Cell(int a, int b): x(a), y(b)
    {
        std::cout << __FUNCTION__;
    }
    ~Cell()
    {
        std::cout << __FUNCTION__;
    }


    bool operator ==(const Cell &cell) const
    {
        return x == cell.x && y == cell.y;
    }

    bool operator <(const Cell &cell) const
    {
        if (x < cell.x)
        {
            return true;
        }
        return y < cell.y;
    }
};

std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
    os << "{" << cell.x << "," << cell.y << "}";
    return os;
}

int main()
{
    //2) 附带地传递内存位置提示 hint 。若可能则调用 a.allocate(n, hint) 。
    //若不可能(例如无双参数成员函数 allocate() ),则调用 a.allocate(n)
    std::allocator<Cell> allocatorCell;
    std::allocator_traits<std::allocator<Cell>> allocator_traitsCell;
    Cell *pointerCell = allocator_traitsCell.allocate(allocatorCell, 10, nullptr);
    for (int i = 0; i < 10; i++)
    {
        //可能,则在 p 所指向的分配的未初始化存储构造 T 类型对象,通过调用
        //a.construct(p, std::forward<Args>(args)...)
        allocator_traitsCell.construct(allocatorCell, (pointerCell + i), i * 100, i * 100);
        std::cout << "  allocator: " << (pointerCell + i) << "  "
                  << *(pointerCell + i) << std::endl;
    }
    std::cout << std::endl;

    //调用 p 所指向对象的析构函数。若可能,则通过调用 a.destroy(p) 这么做。
    //若不可能(例如 a 无成员函数 destroy() ),则直接调用 *p 的析构函数,同 p->~T() 。
    for (int i = 0; i < 10; i++)
    {
        //可能,则在 p 所指向的分配的未初始化存储构造 T 类型对象,通过调用
        //a.construct(p, std::forward<Args>(args)...)
        allocator_traitsCell.destroy(allocatorCell, (pointerCell + i));
        std::cout << "  allocator: " << (pointerCell + i) << "  "
                  << *(pointerCell + i) << std::endl;
    }
    std::cout << std::endl;
    return 0;
}

输出

Cell  allocator: 0x1037ad8  {0,0}
Cell  allocator: 0x1037ae0  {100,100}
Cell  allocator: 0x1037ae8  {200,200}
Cell  allocator: 0x1037af0  {300,300}
Cell  allocator: 0x1037af8  {400,400}
Cell  allocator: 0x1037b00  {500,500}
Cell  allocator: 0x1037b08  {600,600}
Cell  allocator: 0x1037b10  {700,700}
Cell  allocator: 0x1037b18  {800,800}
Cell  allocator: 0x1037b20  {900,900}

~Cell  allocator: 0x1037ad8  {0,0}
~Cell  allocator: 0x1037ae0  {100,100}
~Cell  allocator: 0x1037ae8  {200,200}
~Cell  allocator: 0x1037af0  {300,300}
~Cell  allocator: 0x1037af8  {400,400}
~Cell  allocator: 0x1037b00  {500,500}
~Cell  allocator: 0x1037b08  {600,600}
~Cell  allocator: 0x1037b10  {700,700}
~Cell  allocator: 0x1037b18  {800,800}
~Cell  allocator: 0x1037b20  {900,900}

文章来源:https://blog.csdn.net/qq_40788199/article/details/135187979
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。