这是一个令人尴尬的问题,但即使是boost.interprocess提供的精心编写的文档也不足以让我弄清楚如何做到这一点.
我有一个cached_adaptive_pool分配器实例,我想用它来构造一个对象,传递构造函数参数:
struct Test {
Test(float argument, bool flag);
Test();
};
// Normal construction
Test obj(10, true);
// Normal dynamic allocation
Test* obj2 = new Test(20, false);
typedef managed_unique_ptr<
Test, boost::interprocess::managed_shared_memory>::type unique_ptr;
// Dynamic allocation where allocator_instance == cached_adaptive_pool,
// using the default constructor
unique_ptr obj3 = allocator_instance.allocate_one()
// As above, but with the non-default constructor
unique_ptr obj4 = allocator_instance ... ???
Run Code Online (Sandbox Code Playgroud)
这可能是我在如何使用分配器对象方面的失败.但在任何情况下,我都看不到如何使用这个特定的分配器,使用cached_adaptive_pool中指定的接口将构造函数参数传递给我的对象.
cached_adaptive_pool有方法:void construct(const pointer & ptr, const_reference v)但我不明白这意味着什么,我找不到使用它的例子.
我的头一整天都在模板中游泳,所以即使答案很明显,也会非常感激.
这两个free(NULL)和::operator delete(NULL)是允许的.分配器概念(例如std :: allocator是否允许deallocate(NULL,1),或者是否需要自己保护它?
我在带有MSVC 9.0的Windows 7上使用C++,并且还能够在带有MSVC 9.0的Windows XP SP3上进行测试和再现.
如果我分配1 GB的0.5 MB大小的对象,当我删除它们时,一切正常并且按预期运行.但是,如果在删除它时分配1 GB的0.25 MB大小的对象,则内存保留(地址空间监视器中为黄色),从那时起,只能用于小于0.25 MB的分配.
这个简单的代码将允许您通过更改typedef的结构来测试这两种情况.在分配并删除了结构后,它将分配1 GB的1 MB char缓冲区,以查看char缓冲区是否将使用结构体曾经占用的内存.
struct HalfMegStruct
{
HalfMegStruct():m_Next(0){}
/* return the number of objects needed to allocate one gig */
static int getIterations(){ return 2048; }
int m_Data[131071];
HalfMegStruct* m_Next;
};
struct QuarterMegStruct
{
QuarterMegStruct():m_Next(0){}
/* return the number of objects needed to allocate one gig */
static int getIterations(){ return 4096; }
int m_Data[65535];
QuarterMegStruct* m_Next;
};
// which struct to use
typedef QuarterMegStruct UseType; …Run Code Online (Sandbox Code Playgroud) 当0传递给allocate方法时,可以抛出异常吗?
谢谢.
PS
如果n == 0,则返回值未指定.
这是否意味着不allocate应该抛出异常?我倾向于认为如果n == 0不允许投掷,那么标准就会清楚地说出来.
我有一个非常基本的分配器:
template<typename T>
struct Allocator : public std::allocator<T> {
inline typename std::allocator<T>::pointer allocate(typename std::allocator<T>::size_type n, typename std::allocator<void>::const_pointer = 0) {
std::cout << "Allocating: " << n << " itens." << std::endl;
return reinterpret_cast<typename std::allocator<T>::pointer>(::operator new(n * sizeof (T)));
}
inline void deallocate(typename std::allocator<T>::pointer p, typename std::allocator<T>::size_type n) {
std::cout << "Dealloc: " << n << " itens." << std::endl;
::operator delete(p);
}
template<typename U>
struct rebind {
typedef Allocator<U> other;
};
};
Run Code Online (Sandbox Code Playgroud)
当我使用它时,它工作正常:"std :: vector>",但是,当我尝试将它与std :: map一起使用时:
int main(int, char**) …Run Code Online (Sandbox Code Playgroud) 我最近一直在努力开发基于内存池的自定义分配器,它在分配器的多个实例之间共享.
目的是分配器与STL和基于标准C++的容器兼容,例如vector,deque,map,string等
然而,特别是某些事情让我有些困惑.容器的各种实现(例如std :: vector,std :: string)使用小缓冲区优化 - 基于堆栈的分配用于小的初始内存需求.
例如,MSVC9.1在basic_string类中具有以下成员:
union _Bxty
{ // storage for small buffer or pointer to larger one
_Elem _Buf[_BUF_SIZE];
_Elem *_Ptr;
char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;
Run Code Online (Sandbox Code Playgroud)
我无法看到在实例化这样的容器时,如何只能实现并始终使用提供的分配器而不使用SBO.我问,因为实现自定义分配器的意图之一是能够在共享内存上下文中使用它们,其中共享内存的数量可能小于各种实现可能使用的SBO限制.
例如,我想有一种情况,我可以有两个std :: string实例,每个进程共享一个公共内存块,可能小于或等于SBO上限.
typedef std::vector<int,mysharedmemallocator> shmvtype;
shmvtype v(2,0); //<-- if SBO then error as memory is allocated on
//stack not via the allocator
v[1] = 1234; //<-- if SBO then error as wrong piece of memory …Run Code Online (Sandbox Code Playgroud) 与CodeReview 上的这个问题相关,我尝试使用std::unordered_map自定义分配器,但显然这不适用于gcc/clang和libstdc ++.可以通过使用a初始化空哈希映射来生成错误std::allocator
#include <unordered_map>
int main()
{
typedef std::allocator<std::pair<const int, int>> A;
typedef std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, A> H;
auto h = H{A()}; // ERROR, cannot find constructor H::H(const A&)
}
Run Code Online (Sandbox Code Playgroud)
实例.
问题:libstdc ++是否支持std::unordered_map使用单个分配器构造作为参数不完整?
更新:进一步检查表明,对于除了以外的几乎所有容器std::vector,libstdc ++中的分配器的使用直接访问typedef和分配器的成员函数,而不是通过std::allocator_traits.这适用于std::allocator所有自定义分配器但是失败,除非它们直接添加这些成员和typedef.
我正在尝试重新绑定我的自定义分配器类型MyAllocator<foo>,以便在basic_string类中使用,例如:
std::basic_string<char, std::char_traits<char>, MyAllocator<char>> ...
分配器被传递给上下文MyAllocator<void>,所以我需要重新绑定分配器.
从cppreference页面std::allocator_traits,http://en.cppreference.com/w/cpp/memory/allocator_traits :
成员别名模板:
rebind_alloc<T>:Alloc::rebind<T>::other如果存在,否则Alloc<T, Args>如果此Alloc是Alloc<U, Args>
我的自定义分配器实现allocator_traits,但没有定义重新绑定结构(这似乎不是实现的要求allocator_traits).我对文档的理解是它allocator_traits应该理解rebind_alloc.但是,如果我尝试调用rebind_alloc我的自定义分配器类型:
template<typename T>
using RebindAlloc =
typename std::allocator_traits<MyAllocator<void>>::template rebind_alloc<T>;
Run Code Online (Sandbox Code Playgroud)
我尝试传递RebindAlloc<char>给basic_string类型时遇到各种编译器错误:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/string:52:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/basic_string.h:114:41: error:
'rebind' following the 'template' keyword does not refer to a template
typedef typename _Alloc::template rebind<_CharT>::other _CharT_alloc_type;
Run Code Online (Sandbox Code Playgroud)
很明显,文档误导了我.我应该放弃rebind_alloc并在自定义分配器中实现重新绑定,还是有正确的方法来执行此操作allocator_traits? …
来自http://en.cppreference.com/w/cpp/memory/polymorphic_allocator:
polymorphic_allocator不会在容器副本分配,移动分配或交换上传播.因此,移动分配polymorphic_allocator-using容器可以抛出,并且交换两个polymorphic_allocator使用其分配器不会比较相等的容器导致未定义的行为.
为什么我会想要这种行为?这不仅会在swap上引入无偿的未定义行为,更重要的是,对于我的目的,它意味着它std::pmr::vector实际上是一个不可移动的可分配类型.我的意思是,它是可移动的,但几乎可以保证效率低下.
std::vector<int> v = {1, 2, 3};
std::vector<int> w;
w = std::move(v); // nocopy, nothrow
std::pmr::monotonic_buffer_resource mr(1000);
std::pmr::vector<int> v( {1, 2, 3}, &mr );
std::pmr::vector<int> w;
w = std::move(v); // yescopy, yesthrow
Run Code Online (Sandbox Code Playgroud)
我的猜测是,这是处理所有权问题的原始尝试.在我上面的第二个例子中,v持有一个引用,mr但v实际上并不拥有 mr.允许非拥有引用在整个系统中未经检查地传播将倾向于引入许多微妙的错误.因此,设计人员决定不传播引用,而不是发明拥有的分配器.这最终产生了不良影响,例如移动 - 分配矢量现在复制其数据; 但是你最终还是没有那么多关于内存资源的悬空指针.(有些是,但没有那么多.)mr
PS我已经看到你可以提前设置分配器来避免复制/抛出,如下所示:
std::pmr::monotonic_buffer_resource mr(1000);
std::pmr::vector<int> v( {1, 2, 3}, &mr );
std::pmr::vector<int> w(v.get_allocator());
w = std::move(v); …Run Code Online (Sandbox Code Playgroud) 我试图将Howard stack_allocHinnant 's 与boost rtrees 一起使用,如以下示例所示:
#include "stack_alloc.h"
#include <boost/geometry/index/rtree.hpp>
using NodePoint = boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>;
using Linear = boost::geometry::index::linear<8, 2>;
using RTree =
boost::geometry::index::rtree<NodePoint, Linear, boost::geometry::index::indexable<NodePoint>,
boost::geometry::index::equal_to<NodePoint>,
stack_alloc<NodePoint, 100>>;
int main()
{
RTree my_tree{};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
无法使用相当大的模板错误堆栈进行编译。我认为问题的核心是:
/usr/local/include/boost/geometry/index/detail/rtree/node/variant_static.hpp:26:7:错误:无效使用了不完整的类型'class boost :: geometry :: index :: detail :: rtree: :allocators,100>,boost :: geometry :: model :: point,boost :: geometry :: index :: linear <8,2>,boost :: geometry :: model :: box>,boost :: geometry: :index :: detail :: rtree :: node_variant_static_tag>'
这是带有完整错误的 …