在C++ 11标准中,我们std::scoped_allocator_adaptor在动态内存管理库中.这个班级最重要的用例是什么?
我希望从一个池分配一个shared_ptr管理的对象,比如Boost的Pool接口,怎么能实现呢?
每个allocator类必须具有类似于以下内容的接口:
template<class T>
class allocator
{
...
template<class Other>
struct rebind { typedef allocator<Other> other; };
};
Run Code Online (Sandbox Code Playgroud)
使用分配器的类做了多余的事情:
template<class T, class Alloc = std::allocator<T> >
class vector { ... };
Run Code Online (Sandbox Code Playgroud)
但为什么这有必要呢?
换句话说,他们不能只是说:
template<class T>
class allocator { ... };
template<class T, template<class> class Alloc = std::allocator>
class vector { ... };
Run Code Online (Sandbox Code Playgroud)
哪个更优雅,更少冗余,(在某些类似的情况下)可能更安全?
他们为什么要走这rebind条路,这也会造成更多的冗余(即你要说T两次)?
(类似的问题char_traits和其他问题......尽管它们并非都有rebind,但它们仍然可以从模板模板参数中受益.)
但是,如果您需要多于1个模板参数,这将无效!
实际上,它运作得很好!
template<unsigned int PoolSize>
struct pool
{
template<class T>
struct allocator
{
T pool[PoolSize];
... …Run Code Online (Sandbox Code Playgroud) 所以我在查看规范std::vector并注意到referencetypedef从Allocator::referenceC++ 03变为value_type&C++ 11.我很惊讶,所以我开始深入了解.
在C++03§20.1.5[lib.allocator.requirements]中,表32 X::reference定义为T&并且X::const_reference被定义为T const&.
然而,在C++ 11§17.6.3.5[allocator.requirements]有表28中,reference和const_reference缺失.
接下来我们std::allocator_traits在C++ 11中添加了§20.6.8 ,但不包括reference.但§20.6.9 std::allocator确实如此.
最后,有§23.2.1[container.requirements.general]定义X::reference为"左值T"并且X::const_reference是"const左值T".
所以,我用Google搜索,发现这个文件(1,2)该提议移除reference从分配器的要求,但它并没有提到它后面的任何理由.但也有一个LWG问题反对这一变化.
此外,我找到了亚历山大·斯捷潘诺夫的访谈,其中他谈到了如何reference封装机器特定的内存布局和Herb Sutter的帖子,其中他谈到了指向容器元素,容器要求以及如何std::vector<bool>不是容器的指针.
那么,你怎么看待这一切呢?是reference有用的,做到了服务于它的目的是什么?"花式"引用如何符合标准?这是一个大胆的举措,以完全消除它们,制定更严格的容器要求并弃用std::vector<bool>?
根据C++ Primer第4版,第755页,有一条说明:
现代C++程序通常应该使用allocator类来分配内存.它更安全,更灵活.
我不太明白这个说法.到目前为止,我读过的所有材料都教导用newC++分配内存.本书中展示了向量类如何利用分配器的示例.但是,我想不出其他情况.
任何人都可以帮忙澄清这个陈述吗?并举个更多例子?我应该何时使用分配器以及何时使用new?谢谢!
是否可以使用自定义分配器进行std::vector内部分配?如果有,怎么样?
C++ 允许动态分配零大小的数组:
int* p = new int[0];
delete[] p;
Run Code Online (Sandbox Code Playgroud)
我不能用这样的指针做很多事情(因为数组没有元素),但是新表达式需要给我一个有效的(!= nullptr)指针,然后我必须delete[]再次将它作为一个实际的数组.
有关这种新表达式返回的内存对齐的要求吗?考虑:
struct alignas(8) Foo {
int x;
};
Foo* p = new Foo[0];
delete[] p;
Run Code Online (Sandbox Code Playgroud)
为p保证指向8对齐的地址?此外,如果我编写自定义分配器,在这种情况下我是否需要返回指向对齐地址的指针?
而在寻找的std ::分配器,我看到的成员:
value_type,
pointer,
const_pointer,
reference,
const_reference,
size_type,
difference_type,和
rebind都被废弃了.
分配器也将不再有成员:
address, max_size, construct,或destroy.
为什么会这样?它与多态分配器有关吗?
C++ 17将为我们带来std::pmr::memory_resource一个分配和释放内存的干净界面.与Allocator概念不同,它就是这样,仅此而已.还有一个将std::pmr::polymorphic_allocator内存资源包装到经典分配器中,因此它可以与现有容器一起使用.
如果我要编写一个针对C++ 17及更高版本的新容器(或其他需要大量内存的),我应该继续针对Allocator概念进行编程,还是直接使用更新更清晰的抽象?
截至目前,我的想法是这样的.
继续使用分配器的原因:
std::pmr::*容器别名也继续使用分配器.std::pmr::polymorphic_allocator,因此分配器接口更通用,可以满足更多客户端的需求.开始使用内存资源而不是分配器的原因:
std::pmr::memory_resource界面是干净和简单.std::pmr::polymorphic_allocator.反过来说比较困难.是否已经有关于如何有效使用新库功能的建议?
说我有一个shared_ptr带有自定义分配器和自定义删除器的。
我在标准中找不到任何内容讨论删除器的存储位置:它没有说自定义分配器将用于删除器的内存,也没有说不会。
这是未指定的还是我只是缺少了什么?
allocator ×10
c++ ×10
c++11 ×4
c++17 ×3
stl ×3
shared-ptr ×2
boost ×1
containers ×1
memory ×1
new-operator ×1
templates ×1