代码之家  ›  专栏  ›  技术社区  ›  Zan Lynx

寻找C++类STL类向量,但使用堆栈存储

  •  46
  • Zan Lynx  · 技术社区  · 17 年前

    我正在寻找一个C++类,它几乎完全类似于STL向量,但是将数据存储到堆栈上的数组中。某种类型的STL分配器类也可以工作,但我试图避免任何类型的堆,甚至是静态分配的每线程堆(尽管其中之一是我的第二选择)。堆栈的效率更高。

    它几乎可以替代当前使用向量的代码。

    对于我将要写的东西,我想到了这样的东西:

    char buffer[4096];
    stack_vector<match_item> matches(buffer, sizeof(buffer));
    

    或者该类可以在内部分配缓冲区空间。然后它看起来像:

    stack_vector<match_item, 256> matches;
    

    我在想,如果空间不够,它会抛出std::bad_alloc,尽管这不应该发生。

    使用Chromium的stack_容器。h工作得很好!

    代码有点凌乱,出于某种原因,GCC迫使我将分配器声明为实际项,而不是将其构造为vector的分配器参数。是这样的:

    typedef std::pair< const char *, const char * > comp_list_item;
    typedef std::vector< comp_list_item > comp_list_type;
    
    comp_list_type match_list;
    match_list.reserve(32);
    

    为此:

    static const size_t comp_list_alloc_size = 128;
    typedef std::pair< const char *, const char * > comp_list_item;
    typedef StackAllocator< comp_list_item, comp_list_alloc_size > comp_list_alloc_type;
    typedef std::vector< comp_list_item, comp_list_alloc_type > comp_list_type;
    
    comp_list_alloc_type::Source match_list_buffer;
    comp_list_alloc_type match_list_alloc( &match_list_buffer );
    comp_list_type match_list( match_list_alloc );
    match_list.reserve( comp_list_alloc_size );
    

    10 回复  |  直到 17 年前
        1
  •  49
  •   cidermole    10 年前

    std::vector 为它提供从堆栈缓冲区进行分配的自定义分配器。chromium的作者为此编写了一个分配器:

    https://chromium.googlesource.com/chromium/chromium/+/master/base/stack_container.h

    它的工作原理是在你说它有多大的地方分配一个缓冲区。创建容器并调用 container.reserve(buffer_size); . 如果溢出该大小,分配器将自动从堆中获取元素(因为它是从 std::allocator ,在这种情况下,它将只使用标准分配器的功能)。我没有试过,但它看起来像是来自谷歌的,所以我觉得值得一试。

    StackVector<int, 128> s;
    s->push_back(42); // overloaded operator->
    s->push_back(43);
    
    // to get the real std::vector. 
    StackVector<int, 128>::ContainerType & v = s.container();
    std::cout << v[0] << " " << v[1] << std::endl;
    
        2
  •  21
  •   Community Mohan Dere    6 年前

    看来 boost::static_vector

    静态_向量中的元素数量可能会动态变化,直到固定容量,因为元素存储在对象本身中类似于数组。

        3
  •  11
  •   Michael Burr    15 年前

    您可能希望查看的一些选项:

    Matthew Wilson(不完美C++的作者)的STLSoft有一个 auto_buffer 模板类,该类在堆栈上放置一个默认数组,但如果其增长大于堆栈分配,则将从堆中获取内存。我喜欢这个类-如果您知道您的容器大小通常会受到一个相当低的限制,那么您可以获得本地堆栈分配数组的速度。然而,对于需要更多内存的情况,它仍然可以正常工作。

    http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html

    请注意,我自己使用的实现不是STLSoft的,而是一个大量借鉴STLSoft的实现。

    alloca() 用于存储。我不喜欢这项技术,但我会让你自己决定这是否是你想要的:

    http://tlzprgmr.wordpress.com/2008/04/02/c-how-to-create-variable-length-arrays-on-the-stack/

    然后是 boost::array 它没有前两个的动态大小调整行为,但提供了更多 vector 接口,而不仅仅是使用指针作为迭代器,这是内置数组(即 begin() end() , size() (等):

    http://www.boost.org/doc/libs/1_37_0/doc/html/boost/array.html

        4
  •  6
  •   denis    17 年前

    如果速度很重要,我会看到运行时间

    • 40纳秒 <vector>
    • 1300纳秒 <stlsoft/containers/pod_vector.hpp>

    在一个平台上,仅mac ppc、gcc-4.2-O3。

    不要接受任何你没有伪造的时间。 当然,每种使用模式都是不同的。 尽管如此,这些因素>2.给我一个惊喜。

    (如果mems(内存访问)是运行时的主要因素, 各种实现中的所有额外mems是什么?)

    #include <stlsoft/containers/pod_vector.hpp>
    #include <stdio.h>
    using namespace std;
    
    int main( int argc, char* argv[] )
    {
            // times for 2 push, v[0] v[1], 2 pop, mac g4 ppc gcc-4.2 -O3 --
        // Vecint10 v;  // stack int[10]: 4 ns
        vector<int> v;  // 40 ns
        // stlsoft::pod_vector<int> v;  // 1300 ns
        // stlsoft::pod_vector<int, std::allocator<int>, 64> v;
    
        int n = (argv[1] ? atoi( argv[1] ) : 10) * 1000000;
        int sum = 0;
    
        while( --n >= 0 ){
            v.push_back( n );
            v.push_back( n );
            sum += v[0] + v[1];
            v.pop_back();
            v.pop_back();
        }
        printf( "sum: %d\n", sum );
    
    }
    
        5
  •  5
  •   Mark Ransom    17 年前

    您可以为std::vector使用自己的分配器,并让它分配基于堆栈的存储的块,类似于您的示例。分配器类是模板的第二部分。

    编辑:我从来没有尝试过这个,通过查看文档,我进一步相信您无法编写自己的分配器。我还在调查。

        6
  •  3
  •   Boojum    17 年前

        7
  •  2
  •   Charlie Martin    17 年前

    你为什么要把它放在桌子上 堆栈

        8
  •  2
  •   Sebastian Graf    12 年前

    您可能正在使用Qt。那你可能想去 QVarLengthArray ( docs std::vector std::array ,静态分配一定数量,必要时返回堆分配。

    如果我正在使用的话,我更喜欢boost版本。

        9
  •  1
  •   fandyushin    10 年前

    我有这个。它叫 small_vector

    small_vector是一个类似向量的容器,针对以下情况进行了优化: 包含很少的元素。它包含一些预先分配的元素 当实际元素数低于该值时进行分配 预先分配的阈值。small_vector的灵感来自LLVM的SmallVector 容器与静态_向量不同,小_向量的容量可以增长 超出初始预分配的容量。

    small_vector可转换为small_vector_base,这是一种独立于预分配元素的类型 计数,允许不需要在其上模板化的客户端代码 N参数。小_向量继承所有向量的成员函数,因此 支持所有标准功能,如定位、有状态分配器、, 等

        10
  •  1
  •   MathuSum Mut    8 年前

    StackVector ,一个小型实现,可以这样使用:

    new_stack_vector(Type, name, size)
    

    Type 是向量中元素的类型, name 是向量的变量名,并且 size 是向量中允许的最大元素数。

    可以是变量,不需要是编译时常量!:D

    例子:

    new_stack_vector(int, vec, 100); //like vector<int> vec; vec.reserve(100); but on the stack :)
    vec.push_back(10); //added "10" as the first item in the vector
    

    …就这些!

    免责声明:通常不要在堆栈上使用非常大的数组大小。就像你不应该使用 int var[9999999] ,你同样不应该使用 new_stack_vector(int, vec, 9999999) ! 负责任地使用。

    推荐文章