标签: allocator

`memory_resource`的目的和用法是什么?

该标准C++17包括一个新的命名空间,pmr包括一组以名称分组的类memory_resource.

在网上搜索后,我发现很少有关于它的庸俗信息,直接后果是这个问题:

背后的主要思想pmrpmr::memory_resource什么?


详细说明问题,我头脑中的一些问号是:

  • 它带来了什么新东西,或它解决的限制是什么?
  • 有什么区别allocator
  • 多态是否意味着可以选择allocator提供给容器构造函数的运行时?(例如用于测试目的)
  • 它是否有助于实现内存池或其他内存管理方案?

语境:

在创建memory pool分配器的过程中,我找到了有关此命名空间的信息.读名字pool_options或者polymorphic_allocator引起我的注意.


相关问题:

polymorphic_allocator:何时以及为什么要使用它?

c++ allocator c++17

19
推荐指数
1
解决办法
1680
查看次数

propagate_on_container_move_assignment的示例用法

我试图了解如何正确编写AllocatorAware容器.

我的理解是propagate_on_container_move_assignmenttypedef表示Allocator当Container本身被移动分配时是否需要复制某种类型.

所以,既然我找不到任何这方面的例子,我自己的抨击就像下面这样:

给定容器类型Container,Allocator类型allocator_type和内部allocator_type数据成员m_alloc:

Container& operator = (Container&& other)
{
  if (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
  {
     m_alloc = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
      other.m_alloc
     );
  }

  return *this;
}
Run Code Online (Sandbox Code Playgroud)

它是否正确?

此外,另一个混乱的来源是嵌套的typedef propagate_on_container_move/copy_assignment专门讨论赋值 ...但是构造函数呢?移动构造函数或AllocatorAware容器的复制构造函数是否需要检查这些typedef?我认为这里的答案是肯定的 ......意思是,我还需要写:

Container(Container&& other)
{
      if (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
      {
         m_alloc = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
          other.m_alloc
         );
      }
}
Run Code Online (Sandbox Code Playgroud)

c++ allocator c++11

18
推荐指数
1
解决办法
2488
查看次数

为什么std :: allocator :: deallocate需要大小?

std::allocator是对底层内存模型的抽象,它包含了调用new和的功能delete. delete虽然不需要大小,但是deallocate() 需要它.

void deallocate(T*p,std :: size_t n);
"参数n必须等于最初生成p的allocate()调用的第一个参数;否则,行为是未定义的."

为什么?

现在我要么在解除分配之前进行额外的计算,要么开始存储我传递给分配的大小.如果我没有使用分配器,我就不必这样做了.

c++ memory-management stl allocator delete-operator

17
推荐指数
1
解决办法
1307
查看次数

在具有预分配块的自定义STL分配器中重新绑定

我将构建一个自定义分配器,预分配一个大块(数组)来存储N某些类的元素T,然后只需增加数组内的索引来为服务分配请求.

因为我希望对预分配块中的元素进行任何初始化,所以这样的东西不起作用:

T buffer[N];
Run Code Online (Sandbox Code Playgroud)

因为在这种情况下,T将为N块的元素调用构造函数.

既然我的理解是std::aligned_storage不调用T构造函数,我想使用std::aligned_storage,像这样:

std::aligned_storage<
    N * sizeof(T),
    std::alignment_of<T>::value 
>::type buffer;

T* base = static_cast<T*>( static_cast<void*>(&buffer) );
Run Code Online (Sandbox Code Playgroud)

然后,当请求T的分配(直到(base+N))时,分配器可以仅增加基指针,并且在需要时可以在适当的位置构建T (具有放置new).

我想使用此方案为STL容器定义自定义分配器.但是,在我看来,重新绑定可能存在问题.事实上,如果我的理解是正确的,一个STL分配器应支持从类型重新绑定T到一个类型U,例如,因为喜欢的容器std::list<T>(或其它基于节点的容器一样std::map)使用allocator分配的节点上,但不是类型T,但不同type U(包含T节点的"header"开头信息).那么,上述std::aligned_storage方法是否适用于重新绑定?或者(我认为)Ts 的正确对齐并不意味着另一种不同类型的正确对齐U

怎么可以解决这个问题?

我怎样才能定义上述内容buffer …

c++ memory-management stl allocator c++11

16
推荐指数
1
解决办法
1647
查看次数

如何使用自定义分配器创建std :: function?

为了保存一些代码,我可以说我有一个名为的自定义分配器MyAlloc,我已成功使用std::vector<int>如下:

std::vector<int,MyAlloc<int>> vec;
Run Code Online (Sandbox Code Playgroud)

现在我想使用自定义分配器在std :: function中保存lambda,我该怎么做?

我失败的尝试:

int i[100];
std::function<void(int)> f(MyAlloc<void/*what to put here?*/>{},[i](int in){
    //...
});
Run Code Online (Sandbox Code Playgroud)

更新: std :: function中的分配器已被删除

c++ allocator c++11

16
推荐指数
1
解决办法
4309
查看次数

如何在现代C++中使用allocator

从我在http://en.cppreference.com/w/cpp/memory/allocator中读到的内容来看,分配器的大部分功能现在都将被弃用.问题是,如何在新代码中使用分配器?现在"正确"的方式是什么?

从我在文档中推断出来的,construct是分配器特性的一部分,而不是分配器本身.

我正在构建一个自定义容器,这里是一个非常简单的构造函数版本,这是一个很好的新设计用法吗?

container::container(std::size_t size, T const& value, Allocator const& allocator) : allocator_(allocator){
    data_ = std::allocator_traits<Alloc>::allocate(allocator_, size);
    for(auto ptr = data_; ptr != data_ + size; ++ptr){
        std::allocator_traits<Allocator>::construct(allocator_, ptr, value)
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图std::for_each在循环中使用一个算法(如),但我没有设法使用一个没有地址(operator&).

我在哪里可以找到现代分配器的完整示例?


经过一些调整,我找到了一种方法来使用算法而不是原始循环(可以传递执行策略).我不是很确定,但可能是这样的:

    data_ = std::allocator_traits<Allocator>::allocate(allocator_, size);
    std::for_each([policy? deduced from allocator?,] 
        boost::make_counting_iterator(data_),
        boost::make_counting_iterator(data_ + size), 
        [&](auto ptr){std::allocator_traits<Allocator>::construct(allocator_, ptr, value);}
    );
Run Code Online (Sandbox Code Playgroud)

c++ allocator type-traits c++11 c++17

16
推荐指数
1
解决办法
1801
查看次数

为什么在 C++23 中 allocate_at_least() ?

根据cppref

std::allocator<T>::allocate_at_least

通过调用 (可能提供附加参数)分配count * sizeof(T)未初始化存储的字节,其中 count是不小于 的未指定整数值,但未指定何时以及如何调用此函数。n::operator newstd::align_val_t

T[count]然后,该函数在存储中创建一个类型数组并开始其生命周期,但不会启动其任何元素的生命周期。

然而,我认为现有的std::allocator<T>::allocate可以做同样的事情。

为什么我们需要 std::allocator<T>::allocate_at_least C++23?

c++ performance standards allocator c++23

16
推荐指数
2
解决办法
1065
查看次数

旧的alloctaor :: construct与新的alloctaor:和显式构造函数之间有什么区别?

据我所知std::allocator<T>::construct,在旧版本的C ++上仅需要两个参数;第一个是指向未构建的原始内存的指针,我们要在其中构造一个类型的对象,T第二个是用于初始化该对象的元素类型的值。因此,调用了复制构造函数:

struct Foo {
    Foo(int, int) { cout << "Foo(int, int)" << endl; }
    /*explicit*/ Foo(int) { cout << "Foo(int)" << endl; }
    Foo(const Foo&) { cout << "Foo(const Foo&)" << endl; }
};

int main(int argc, char* argv[]) {


    allocator<Foo> a;
    Foo* const p = a.allocate(200, NULL); // second parameter is required on C++98 but on C++11 it is optional
//  Foo* const p = a.allocate(200); // works fine on C++11 but not on …
Run Code Online (Sandbox Code Playgroud)

c++ allocator

15
推荐指数
1
解决办法
165
查看次数

STL容器:构造函数的Allocator参数和作用域分配器

STL容器有一个模板参数来选择自定义分配器.花了一段时间,但我想我明白它是如何工作的.不知何故,它不是很好,因为给定的分配器类型不是直接使用,而是反弹到另一种类型的分配器.最后我可以使用它.

在阅读API之后,我意识到还有可能将allocator作为构造函数参数.但是,我如何知道容器使用哪种分配器,如果它在内部从模板参数重新绑定给定的分配器?

另外我读到C++ 11现在使用范围分配器,它允许重用容器的分配器来容纳容器.如何启用作用域分配器容器的实现与不知道作用域容器的容器大致不同?

不幸的是,我无法找到任何可以解释这一点的东西.谢谢你的回答!

c++ containers stl allocator c++11

14
推荐指数
1
解决办法
3451
查看次数

自定义分配器可以替代智能指针的向量?

这个问题是关于拥有指针,使用指针,智能指针,向量和分配器的。

我对代码体系结构的想法有些迷茫。此外,如果这个问题在某个地方已经有答案,1.抱歉,但是到目前为止我还没有找到满意的答案,并且2.请指出。

我的问题如下:

我有一个存储在向量中的“事物”,以及这些“事物”的几个“消费者”。因此,我的第一次尝试如下所示:

std::vector<thing> i_am_the_owner_of_things;
thing* get_thing_for_consumer() {
    // some thing-selection logic
    return &i_am_the_owner_of_things[5]; // 5 is just an example
}

...

// somewhere else in the code:
class consumer {
    consumer() {
       m_thing = get_thing_for_consumer();
    }

    thing* m_thing;
};
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,这是安全的,因为在任何情况下,“事物”的寿命都超过了“消费者”。但是,可以在运行时添加更多的“事物”,这可能会成为问题,因为如果std::vector<thing> i_am_the_owner_of_things;重新分配了这些事物,则所有thing* m_thing指针都将变为无效。

一种解决方案是将唯一的指针存储到“事物”,而不是直接存储“事物”,即如下所示:

std::vector<std::unique_ptr<thing>> i_am_the_owner_of_things;
thing* get_thing_for_consumer() {
    // some thing-selection logic
    return i_am_the_owner_of_things[5].get(); // 5 is just an example
}

...

// somewhere else in the code:
class consumer {
    consumer() {
       m_thing …
Run Code Online (Sandbox Code Playgroud)

c++ shared-ptr allocator unique-ptr c++11

14
推荐指数
1
解决办法
602
查看次数