简体   繁体   English

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

[英]How to use allocators in modern C++

From what I read in http://en.cppreference.com/w/cpp/memory/allocator , most features of the allocators are now going to be deprecated. 从我在http://en.cppreference.com/w/cpp/memory/allocator中读到的内容来看,分配器的大部分功能现在都将被弃用。 The question is, how is one supposed to use allocators in new code? 问题是,如何在新代码中使用分配器? What is the "right" way now? 现在“正确”的方式是什么?

From what I deduce in the documentation, construct is part of the allocator traits, rather than the allocator itself. 从我在文档中推断出, construct是分配器特征的一部分,而不是分配器本身。

I am building a custom container, here it is a very simple version of the constructor, is this a good usage of the new design? 我正在构建一个自定义容器,这里是一个非常简单的构造函数版本,这是一个很好的新设计用法吗?

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)
    }
}

I tried to use an algorithm (like std::for_each ) in the loop but I didn't manage to use one without taking addresses ( operator& ). 我试图在循环中使用一个算法(如std::for_each ),但我没有设法使用一个没有地址( operator& )。

Where can I find a complete example of a modern allocator? 我在哪里可以找到现代分配器的完整示例?


After some tweaking, I found a way to use an algorithm instead of the the raw loop (to which an execution policy can be passed). 经过一些调整,我找到了一种方法来使用算法而不是原始循环(可以传递执行策略)。 I am not very sure, but it could be this: 我不是很确定,但可能是这样的:

    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);}
    );

Yes, the current approach is through std::allocator_traits . 是的,目前的方法是通过std::allocator_traits You'll be able to support the "minimal allocator interface" that way. 你将能够以这种方式支持“最小分配器接口”。

http://en.cppreference.com/w/cpp/concept/Allocator http://en.cppreference.com/w/cpp/concept/Allocator

Some requirements are optional: the template std::allocator_traits supplies the default implementations for all optional requirements, and all standard library containers and other allocator-aware classes access the allocator through std::allocator_traits , not directly. 一些需求是可选的:模板std::allocator_traits提供所有可选需求的默认实现,并且所有标准库容器和其他分配器识别类通过std::allocator_traits访问std::allocator_traits ,而不是直接访问。

If you observe the std::allocator_traits member functions and typedefs, you'll see they're detecting the presence of appropriate function/types and dispatching through them if they can. 如果你观察到std::allocator_traits成员函数和typedef,你会发现他们正在检测是否存在适当的函数/类型,并且如果可以的话就调度它们。

The deprecation and potential future removal will change nothing if you're already using std::allocator_traits since it only applies to std::allocator and their member functions/typedefs. 如果您已经使用std::allocator_traits ,则弃用和潜在的将来删除将不会改变,因为它仅适用于std::allocator及其成员函数/ typedef。

Now, if you ask me, there's nothing wrong with for-loops, and using std::for_each gains you nothing. 现在,如果你问我,for循环没有问题,使用std::for_each什么都不会获得。 There are several uninitialized_* functions, but they use placement new directly. 有几个uninitialized_*函数,但它们直接使用placement new。 If you really care you can extract this code to a separate construct_range function. 如果您真的在意,可以将此代码提取到单独的construct_range函数中。

There's also an exception safety issue - in case one of the constructors throws, you need to destroy the earlier elements in order to satisfy the strong exception guarantee and free the memory too (destructor won't get called in case constructor throws) 还有一个异常安全问题 - 如果其中一个构造函数抛出,你需要销毁前面的元素以满足强大的异常保证并释放内存(析构函数不会在构造函数抛出的情况下被调用)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM