Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类似向量的容器,其实例的存储是相互连续的?_C++_C++11_Memory Management_Vector_Stl - Fatal编程技术网

C++ 类似向量的容器,其实例的存储是相互连续的?

C++ 类似向量的容器,其实例的存储是相互连续的?,c++,c++11,memory-management,vector,stl,C++,C++11,Memory Management,Vector,Stl,我需要一个容器类,其API尽可能接近std::vector(除了不重新分配),但其元素的存储(而不是其成员变量,如大小)可以指定为从现有缓冲区分配,这样我就可以在连续缓冲区中保留所有vector的元素。也就是说,一个向量的.end()指向缓冲区中与下一个向量的.front()相同的元素 我不知道是否可以简单地将自定义分配器与std::vector一起使用,因为我找不到关于该分配器是为整个类分配存储的信息,包括大小和指针数据成员(在这种情况下,我不能使用这种方法),还是只为它所持有的数据元素(在这

我需要一个容器类,其API尽可能接近std::vector(除了不重新分配),但其元素的存储(而不是其成员变量,如大小)可以指定为从现有缓冲区分配,这样我就可以在连续缓冲区中保留所有vector的元素。也就是说,一个向量的.end()指向缓冲区中与下一个向量的.front()相同的元素

我不知道是否可以简单地将自定义分配器与std::vector一起使用,因为我找不到关于该分配器是为整个类分配存储的信息,包括大小和指针数据成员(在这种情况下,我不能使用这种方法),还是只为它所持有的数据元素(在这种情况下,我可以使用它)

我只需要一个实例的存储分配一次,所以重新分配没有问题。我在这里发帖是想看看是否已经发布了这样一个容器,而不是从头开始用迭代器等重新实现大多数std向量接口


更新:我取消了发布的答案,因为它在VisualC++ 2012中调试模式下不起作用。带有

T
=
float
的示例:

template<class T>
inline typename ContigAlloc<T>::pointer ContigAlloc<T>::allocate(std::size_t n)
{
    std::cout << "Alloc " << n << "; type match: " << std::boolalpha << std::is_same<T, float>::value << std::endl;
    return reinterpret_cast<T *>(_buff.alloc(T * sizeof(n)));
}

template<class T>
inline void ContigAlloc<T>::deallocate(T *p, std::size_t n) // TODO: noexcept when VC++2013
{
    std::cout << "Deall " << n << "; type match: " << std::boolalpha << std::is_same<T, float>::value << std::endl;
    _buff.dealloc(p, T * sizeof(n));
}
调试生成的结果不正确:


在对
allocate()
的第一次调用中,分配器仅用于为元素分配存储。为此,可以使用自定义分配器

乔恩在下面的评论中纠正了我的错误

我认为可以实现一个一致的
向量
,这样它就可以存储堆中除了指针以外的所有内容。堆上的内容可能是3个指针加上分配器(如果不是分配器,则未优化掉),或者是1个指针、大小和容量(以及可能优化掉的分配器)

实际上,
std::vector
的每一个单独实现都以任何形式发布,包括:

  • 惠普
  • SGI
  • libstdc++(gcc)
  • libc++(llvm)
  • 纯粹的器皿
  • 微软
  • 流氓波
  • 代码战士
  • STLPort
  • 我肯定我忘了其他人
已将所有支持成员放置在vector类本身中,并且仅使用分配器分配数据。而且似乎没有什么动力去做其他事情

所以这是事实上的标准,不是官方标准。鉴于上述历史,这是一个相当安全的过程

请注意,
string
在概念上具有相同的布局,因此不能做出相同的声明。
string
的C++11实现通常使用“短字符串”优化,其中分配器根本不用于“短”字符串,而是将值嵌入到string类中。23.2.1一般集装箱要求[container.requirements.General]/10:

(除非另有规定)任何swap()函数都不会使任何 引用的元素的引用、指针或迭代器 正在交换的容器


如果我正确理解你的问题,你使用的是固定大小的向量。 如果这些大小和向量的数量是编译时常量,我建议使用
std::array

编辑: 为了澄清我的意思,这里有一个例子:

struct Memory {
    std::array<int, 2> a1; 
    std::array<int, 2> a2;
} memory; 


int main() {         
    std::array<int, 2>& a1 = memory.a1;
    std::array<int, 2>& a2 = memory.a2; 

    a1[0] = 10; 
    a1[1] = 11;  
    a2[0] = 20;
    a2[1] = 21;  

    int *it=&(a1[0]); 

    for (size_t i = 0; i < 4; ++i){
        std::cout << *(it++) << ",";
    }
}
struct内存{
std::数组a1;
std::数组a2;
}记忆;
int main(){
std::array&a1=memory.a1;
std::array&a2=memory.a2;
a1[0]=10;
a1[1]=11;
a2[0]=20;
a2[1]=21;
int*it=&(a1[0]);
对于(尺寸i=0;i<4;++i){

STD:CUT

我把它放在GCC和Visual C++ 2012中,所以我发布了,以防其他人碰到这个问题。我必须在我的分配器类中添加以下内容:

template<class U>
struct rebind
{
    typedef typename std::conditional<std::is_same<T, U>::value, ContigAlloc<U>, std::allocator<U>>::type other;
}

template<class U>
inline operator std::allocator<U>(void) const
{
    return std::allocator<U>();
}
模板
结构重新绑定
{
typedef typename std::conditional::type other;
}
模板
内联运算符std::分配器(void)常量
{
返回std::allocator();
}
对于Visual C++2012,在调试构建中,似乎需要条件typedef和转换运算符


这只有在默认的std::分配器是无状态的情况下才起作用,我认为标准中没有指定这一点。

所以您需要一些类似于向量的接口来查看现有的缓冲区?这与Java的ByteBuffer差不多。但是,我需要它具有std::vector的大多数类型特征,因为这个容器将由当前使用std::vector并使用其迭代器等的类使用。@DisplayName:?正如您提到的ByteBuffer。这正是
vector
具有
分配器
模板参数的原因。请阅读分配器:@EduardoLeón,C++14将不具有
std::dynarray
。未来的数组扩展将支持bably有
std::experimental::dynarray
,但没有C++14(您链接到的页面上甚至有这样的说明)我正在查看该标准,以找到对该标准的引用,但我不能。我能做的最好是间接的,例如,
shared\u ptr
的某些构造函数特别声明其分配器将用于分配内部状态,而
vector
上的任何内容都没有这样的说明。但这足以保证吗?你能透露一些信息吗t请?“我认为可以实现一个一致性向量,这样它就可以在堆上存储除指针以外的所有内容。”如果值类型是UDT,则需要重新绑定分配器,以便在空闲存储上分配和构造大小等(23.2.1/7)“此分配器的副本用于在每个容器对象的生存期内或替换分配器之前,由这些构造函数和所有成员函数执行的任何内存分配。”)据我所知,非反弹分配器将仅用于元素。@dyp:容器不是必需的(但允许使用)要存储非回弹分配
Alloc 1; type match: false
Alloc 1; type match: true
Alloc 2; type match: true
Deall 1; type match: true
Deall 2; type match: true
Deall 1; type match: false
struct Memory {
    std::array<int, 2> a1; 
    std::array<int, 2> a2;
} memory; 


int main() {         
    std::array<int, 2>& a1 = memory.a1;
    std::array<int, 2>& a2 = memory.a2; 

    a1[0] = 10; 
    a1[1] = 11;  
    a2[0] = 20;
    a2[1] = 21;  

    int *it=&(a1[0]); 

    for (size_t i = 0; i < 4; ++i){
        std::cout << *(it++) << ",";
    }
}
template<class U>
struct rebind
{
    typedef typename std::conditional<std::is_same<T, U>::value, ContigAlloc<U>, std::allocator<U>>::type other;
}

template<class U>
inline operator std::allocator<U>(void) const
{
    return std::allocator<U>();
}