C++ Boost容器向量可以通过非原始指针管理内存吗?
我有一个类似指针的结构,它代替了指针。 指针的区别在于它有额外的信息(也是特殊的)分配器可以用来释放内存 这种类似指针的结构适用于所有基本用途。 我可以分配和取消分配内存、删除、增量、C++ Boost容器向量可以通过非原始指针管理内存吗?,c++,pointers,boost,boost-interprocess,boost-container,C++,Pointers,Boost,Boost Interprocess,Boost Container,我有一个类似指针的结构,它代替了指针。 指针的区别在于它有额外的信息(也是特殊的)分配器可以用来释放内存 这种类似指针的结构适用于所有基本用途。 我可以分配和取消分配内存、删除、增量、->等 现在我想用这个指针来管理一个类似STL的容器。 早些时候,我意识到STL向量基本上不能处理非原始指针。 T*太硬了,标准基本上排除了任何非指针的内容 受Boost.Interprocess“offset\u ptr的启发,我决定使用Boost.Containervector,它非常可定制,原则上可以管理任何
->
等
现在我想用这个指针来管理一个类似STL的容器。
早些时候,我意识到STL向量基本上不能处理非原始指针。
T*
太硬了,标准基本上排除了任何非指针的内容
受Boost.Interprocess“offset\u ptr
的启发,我决定使用Boost.Containervector
,它非常可定制,原则上可以管理任何东西,传递给Boost::Container::vector
的分配器可以处理任何类似指针的东西
现在类boost::container::vector
可以做任何事情。。。除了resize()
强>
查看boost/container/vector.hpp中的代码,似乎调整大小的过程(基本上是复制和分配,然后是复制(或移动)和释放)涉及到原始指针
令人不快的是:
[line 2729:] T * const new_buf = container_detail::to_raw_pointer
(allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start));
随后是
[line 3022:] this->m_holder.start(new_start); // new_start is the same as new_buf above.
// member ::start(pointer&) will need to convert a raw pointer to the pointer typedef.
这两行绝对消除了使用非原始指针的可能性。即使我有一个到原始指针的转换操作符,关于特殊指针的其他信息也会丢失
这个小细节禁止使用非原始指针,这似乎很愚蠢。考虑到容器的通用性(例如定义指针
typedef),为什么这部分代码只使用T*
调整大小
换句话说,为什么Boost容器不使用这一行呢
[alternative] pointer const new_buf =
allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start);
使用Boost容器向量处理非原始指针是否有解决方法或替代方法?
容器在其手册页面上说
容器是一项长期开发工作的产物
2004年,实验性的Shmem图书馆率先使用
共享内存中的标准容器。Shmem包括修改的SGI
STL容器代码经过调整以支持非原始类型
和有状态分配器。经审查后,Shmem被视为
Interprocess和这个库继续完善和改进
那些容器
当前的实现(在调整大小的上下文中)与此设计目标背道而驰
我在这里问了一个不太具体的问题,关于分配器的其他特性:
作为参考,指定特殊指针(传播到容器)的分配器如下所示
template<class T>
struct allocator{
using value_type = T;
using pointer = array_ptr<T>; // simulates T*
using const_pointer = array_ptr<T const>; // simulates T const*
using void_pointer = array_ptr<void>; // simulates void*
using const_void_pointer = array_ptr<void const>; // simulates void const*
some_managed_shared_memory& msm_;
allocator(some_managed_shared_memory& msm) : msm_(msm){}
array_ptr<T> allocate(mpi3::size_t n){
auto ret = msm_.allocate(n*sizeof(T));
return static_cast<array_ptr<T>>(ret);
}
void deallocate(array_ptr<T> ptr, mpi3::size_t = 0){
msm_.deallocate(ptr);
}
};
模板
结构分配器{
使用值_type=T;
使用指针=数组_ptr;//T*
使用const\u pointer=array\u ptr;//模拟T const*
使用void\u pointer=array\u ptr;//模拟void*
使用const\u void\u pointer=array\u ptr;//模拟void const*
一些受管理的共享内存&msm;
分配器(一些受管理的共享内存和msm):msm(msm){
数组\u ptr分配(mpi3::大小\u t n){
自动重新分配=msm_u.allocate(n*sizeof(T));
返回静态输出
#包括
#包括
模板
结构数组;
模板
结构数组{
使用T=void;
T*p;
int i;//一些附加信息
//T&运算符*()常量{return*p;}
T*运算符->()常量{return p;}
//运算符T*()常量{return p;}
模板
运算符数组_ptr()常量{返回数组_ptr((TT*)p,i);}
运算符bool()常量{return p;}
数组_ptr(){}
数组ptr(std::nullptr_t):p(nullptr){
数组ptr(T*ptr,int_i):p(ptr),i(_i){
模板
array_ptr(array_ptr other):p(other.p),i(other.i){}
};
模板
结构数组{
使用T=无效常数;
T*p;
int i;//一些附加信息
//T&运算符*()常量{return*p;}
T*运算符->()常量{return p;}
运算符T*()常量{return p;}
数组_ptr(){}
数组ptr(std::nullptr_t):p(nullptr){
数组ptr(T*ptr,int_i):p(ptr),i(_i){
模板
array_ptr(array_ptr other):p(other.p),i(other.i){}
};
模板
结构数组{
T*p;
int i;//一些附加信息
T&运算符*()常量{return*p;}
T*运算符->()常量{return p;}
运算符[](标准::大小)常量(&T){
断言(i==99);
返回*(p+n);
}
布尔运算符==(数组_ptr const&other)const{return p==other.p和i==other.i;}
布尔运算符!=(数组_ptr const&other)const{return not((*this)=other);}
//运算符T*()常量{return p;}
数组_ptr&operator++(){++p;返回*this;}
数组\u ptr&operator+=(std::ptrdiff\u t n){p+=n;返回*this;}
数组\u ptr&运算符-=(std::ptrdiff\u t n){p-=n;返回*this;}
array_ptr操作符+(std::size_t n)const{array_ptr ret(*this);ret+=n;return ret;}
std::ptrdiff_t运算符-(array_ptr const&other)const{return p-other.p;}
数组_ptr(){}
数组ptr(std::nullptr_t):p(nullptr),i(0){
运算符bool()常量{return p;}
数组ptr(T*ptr,int_i):p(ptr),i(_i){
数组_ptr(T*ptr):p(ptr),i(0){
数组_ptr(int):p(nullptr),i(0){
array_ptr(array_ptr const&other):p(static_cast(other.p)),i(other.i){
};
构造一些\u管理\u共享\u内存{
array_ptr allocate(size_t n){返回array_ptr(::malloc(n),99);}
无效释放(数组_ptr ptr){if(ptr)::free(ptr.p);}
};
模板
结构分配器{
使用值_type=T;
使用指针=数组_ptr;//T*
使用const\u pointer=array\u ptr;//模拟T const*
使用void\u pointer=array\u ptr;//模拟void*
使用const\u void\u pointer=array\u ptr;//模拟void const*
某些成员管理共享
#include<iostream>
#include <boost/container/vector.hpp>
template<typename T>
struct array_ptr;
template<>
struct array_ptr<void> {
using T = void;
T* p;
int i; //some additional information
// T& operator*() const { return *p; }
T* operator->() const { return p; }
// operator T*() const { return p; }
template<class TT>
operator array_ptr<TT>() const{return array_ptr<TT>((TT*)p, i);}
operator bool() const{return p;}
array_ptr(){}
array_ptr(std::nullptr_t) : p(nullptr){}
array_ptr(T* ptr, int _i) : p(ptr), i(_i){}
template<class Other>
array_ptr(array_ptr<Other> other) : p(other.p), i(other.i){}
};
template<>
struct array_ptr<void const> {
using T = void const;
T* p;
int i; //some additional information
// T& operator*() const { return *p; }
T* operator->() const { return p; }
operator T*() const { return p; }
array_ptr(){}
array_ptr(std::nullptr_t) : p(nullptr){}
array_ptr(T* ptr, int _i) : p(ptr), i(_i){}
template<class Other>
array_ptr(array_ptr<Other> other) : p(other.p), i(other.i){}
};
template<typename T>
struct array_ptr {
T* p;
int i; //some additional information
T& operator*() const { return *p; }
T* operator->() const { return p; }
T& operator[](std::size_t n) const{
assert(i == 99);
return *(p + n);
}
bool operator==(array_ptr const& other) const{return p == other.p and i == other.i;}
bool operator!=(array_ptr const& other) const{return not((*this)==other);}
// operator T*() const { return p; }
array_ptr& operator++(){++p; return *this;}
array_ptr& operator+=(std::ptrdiff_t n){p+=n; return *this;}
array_ptr& operator-=(std::ptrdiff_t n){p-=n; return *this;}
array_ptr operator+(std::size_t n) const{array_ptr ret(*this); ret+=n; return ret;}
std::ptrdiff_t operator-(array_ptr const& other) const{return p - other.p;}
array_ptr(){}
array_ptr(std::nullptr_t) : p(nullptr), i(0){}
operator bool() const{return p;}
array_ptr(T* ptr, int _i) : p(ptr), i(_i){}
array_ptr(T* ptr) : p(ptr), i(0){}
array_ptr(int) : p(nullptr), i(0){}
array_ptr(array_ptr<void> const& other) : p(static_cast<T*>(other.p)), i(other.i){}
};
struct some_managed_shared_memory {
array_ptr<void> allocate(size_t n) { return array_ptr<void>(::malloc(n), 99); }
void deallocate(array_ptr<void> ptr) { if (ptr) ::free(ptr.p); }
};
template<typename T>
struct allocator{
using value_type = T;
using pointer = array_ptr<T>; // simulates T*
using const_pointer = array_ptr<T const>; // simulates T const*
using void_pointer = array_ptr<void>; // simulates void*
using const_void_pointer = array_ptr<void const>; // simulates void const*
some_managed_shared_memory& msm_;
allocator(some_managed_shared_memory& msm) : msm_(msm){}
array_ptr<T> allocate(size_t n){
auto ret = msm_.allocate(n*sizeof(T));
return static_cast<array_ptr<T>>(ret);
}
void deallocate(array_ptr<T> ptr, std::size_t = 0){
msm_.deallocate(ptr);
}
};
int main() {
some_managed_shared_memory realm;
boost::container::vector<int, allocator<int> > v(10, realm);
assert( v[4] == 0 );
v[4] = 1;
assert( v[4] == 1 );
for(std::size_t i = 0; i != v.size(); ++i) std::cout << v[i] << std::endl;
for(auto it = v.begin(); it != v.end(); ++it) std::cout << *it << std::endl;
// none of these compile:
v.push_back(8);
assert(v.size() == 11);
v.resize(100);
std::cout << v[89] << std::endl; // will fail an assert because the allocator information is lost
//v.assign({1,2,3,4,5});
}
using version = boost::container::version_0; // seems unsupported, really
using version = boost::container::version_1;
using version = boost::container::version_2; // does different operations
std::cout << boost::container::container_detail::impl::version<allocator<int> >::value << "\n";
array_ptr<int> p;
auto rawp = boost::container::container_detail::to_raw_pointer(p);
std::cout << typeid(rawp).name() << "\n";
std::cout << typeid(p).name() << "\n";
std::cout << typeid(p + 5).name() << "\n";
std::cout << typeid(p - 5).name() << "\n";
1
int*
array_ptr<int>
int*
int*
template <typename T, typename N>
array_ptr<T> operator+(array_ptr<T> const& p, N n) { return array_ptr<T>(p.p+n, p.i); }
template <typename T>
array_ptr<T>& operator++(array_ptr<T>& p) { return ++p.p, p; }
template <typename T>
array_ptr<T> operator++(array_ptr<T>& p, int) { auto q = p.p++; return array_ptr<T>(q, p.i); }
template <typename T, typename N>
array_ptr<T> operator-(array_ptr<T> const& p, N n) { return array_ptr<T>(p.p-n, p.i); }
template <typename T>
ptrdiff_t operator-(array_ptr<T> const& a, array_ptr<T> const& b) { return a.p - b.p; }
1
int*
array_ptr<int>
array_ptr<int>
array_ptr<int>
array_pointer<T> p;
auto* rawp = to_raw_pointer(p);
array_pointer<T> clone(rawp); // oops lost the extra info in p
#if COMPILATION_INSTRUCTIONS
clang++ -std=c++14 -Wall -Wfatal-errors $0 -o $0x.x && $0x.x $@ && rm -f $0x.x; exit
#endif
#define DEFAULT_DATA = 0
#define DEFINE_ARITHMETIC_OPERATIONS
#include <iostream>
#include <boost/container/vector.hpp>
#include <typeinfo>
template<typename T>
struct array_ptr {
T* p;
int i; //some additional information
T& operator*() const { return *p; }
T* operator->() const { return p; }
operator T*() const { return p; }
array_ptr(){}
//array_ptr(std::nullptr_t) : p(nullptr), i(0){}
array_ptr(T* ptr, int _i DEFAULT_DATA) : p(ptr), i(_i){}
};
template<>
struct array_ptr<void> {
using T = void;
T* p;
int i; //some additional information
// T& operator*() const { return *p; }
T* operator->() const { return p; }
operator T*() const { return p; }
template<class T>
operator array_ptr<T>() const{return array_ptr<T>((T*)p, i);}
// array_ptr& operator++(){++p; return *this;}
array_ptr(){}
array_ptr(std::nullptr_t) : p(nullptr){}
array_ptr(T* ptr, int _i DEFAULT_DATA) : p(ptr), i(_i){}
template<class Other>
array_ptr(array_ptr<Other> other) : p(other.p), i(other.i){}
};
template<>
struct array_ptr<void const> {
using T = void const;
T* p;
int i; //some additional information
// T& operator*() const { return *p; }
T* operator->() const { return p; }
operator T*() const { return p; }
// array_ptr& operator++(){++p; return *this;}
// template<class Other> array_ptr(array_ptr<Other> const& other) : p(other.p), i(other.i){}
array_ptr(){}
array_ptr(std::nullptr_t) : p(nullptr){}
array_ptr(T* ptr, int _i DEFAULT_DATA) : p(ptr), i(_i){}
template<class Other>
array_ptr(array_ptr<Other> other) : p(other.p), i(other.i){}
};
struct some_managed_shared_memory {
array_ptr<void> allocate(size_t n) { return array_ptr<void>(::malloc(n), 99); }
void deallocate(array_ptr<void> ptr) { if (ptr) ::free(ptr.p); }
};
template<typename T>
struct allocator{
using version = boost::container::version_1;
using value_type = T;
using pointer = array_ptr<T>; // simulates T*
using const_pointer = array_ptr<T const>; // simulates T const*
using void_pointer = array_ptr<void>; // simulates void*
using const_void_pointer = array_ptr<void const>; // simulates void const*
some_managed_shared_memory& msm_;
allocator(some_managed_shared_memory& msm) : msm_(msm){}
array_ptr<T> allocate(size_t n){
auto ret = msm_.allocate(n*sizeof(T));
return static_cast<array_ptr<T>>(ret);
}
void deallocate(array_ptr<T> ptr, std::size_t = 0){
msm_.deallocate(ptr);
}
};
#ifdef DEFINE_ARITHMETIC_OPERATIONS
template <typename T, typename N>
array_ptr<T> operator+(array_ptr<T> const& p, N n) { return array_ptr<T>(p.p+n, p.i); }
template <typename T>
array_ptr<T>& operator++(array_ptr<T>& p) { return ++p.p, p; }
template <typename T>
array_ptr<T> operator++(array_ptr<T>& p, int) { auto q = p.p++; return array_ptr<T>(q, p.i); }
template <typename T, typename N>
array_ptr<T> operator-(array_ptr<T> const& p, N n) { return array_ptr<T>(p.p-n, p.i); }
template <typename T>
ptrdiff_t operator-(array_ptr<T> const& a, array_ptr<T> const& b) { return a.p - b.p; }
#endif
int main() {
std::cout << boost::container::container_detail::impl::version<allocator<int> >::value << "\n";
if (1) { // some diagnostics
array_ptr<int> p;
auto rawp = boost::container::container_detail::to_raw_pointer(p);
std::cout << typeid(rawp).name() << "\n";
std::cout << typeid(p).name() << "\n";
std::cout << typeid(p + 5).name() << "\n";
std::cout << typeid(p - 5).name() << "\n";
}
some_managed_shared_memory realm;
boost::container::vector<int, allocator<int> > v(10, realm);
assert( v[4] == 0 );
v[4] = 1;
assert( v[4] == 1 );
for(std::size_t i = 0; i != v.size(); ++i) std::cout << v[i] << std::endl;
// these compile:
v.push_back(12);
v.resize(100);
v.assign({1,2,3,4,5});
}
1
Pi
9array_ptrIiE
9array_ptrIiE
9array_ptrIiE
0
0
0
0
1
0
0
0
0
0