变长 std::array 像

Posted

技术标签:

【中文标题】变长 std::array 像【英文标题】:Variable-length std::array like 【发布时间】:2014-01-18 09:40:51 【问题描述】:

由于我通常使用的 C++ 编译器允许可变长度数组(例如,取决于运行时大小的数组),我想知道是否有类似 std::array 的可变大小的东西?当然std::vector 的大小是可变的,但它在堆上分配,并在需要时重新分配。

我喜欢在运行时定义大小的堆栈分配数组。是否有任何 std-template 可能具有此功能?也许使用具有固定最大尺寸的std::vector

【问题讨论】:

使用std::array时,数组的大小是模板参数,所以不能是运行时变量。我猜std::vector 是你最好的选择。 由于语言标准中没有“堆栈”,因此很难使这个问题准确或有意义。 @DanielKamilKozar:嗯。使这样的概念精确化将是类型系统上的一个非常奇怪的缺陷。您可以在 Github 上的修订历史中看到自己的努力。到目前为止,这个想法是“没有足够的经验”,所以它被推迟了。 对此的通常答案是将std::vector 与自定义分配器一起使用。由于您希望数据位于“堆栈上”,因此大概它们将始终以与分配相反的顺序被释放。考虑到这个限制,编写一个极快的线程本地分配器应该很容易。缺点是您将预先进行单独的分配来存储数据,但这与操作系统为您的线程堆栈所做的并没有什么不同 - 在现代操作系统上,您的块在使用之前是虚拟的,就像堆栈。但它不会从堆栈中的热缓存中受益。 @KerrekSB:你是什么意思,没有“堆栈”?自动存储的行为就像堆栈一样,语言规范有时将其称为堆栈(例如,抛出异常时的“堆栈展开”),那么为什么不将其称为堆栈呢? 【参考方案1】:

目前正在制定两个建议,将运行时固定大小的数组引入 C++,您可能会感兴趣:

Runtime-sized arrays with automatic storage duration。这将使运行时大小的数组成为一种语言特性(如在 C11 中)。所以你可以这样做:

  void foo(std::size_t size) 
    int arr[size];
  

C++ Dynamic Arrays。这将为库带来一个新容器std::dynarray,该容器在构造时具有固定大小。它旨在优化以尽可能在堆栈上分配。

  void foo(std::size_t size) 
    std::dynarray<int> arr(size);
  

这些都作为数组扩展技术规范的一部分进行工作,该规范将与 C++14 一起发布。

更新:std::dynarray 尚未实现(2021 年 8 月 25 日)。请参考 What is the status on dynarrays?

【讨论】:

所以第二个看起来真的很好。到今天为止有实现吗? @JosephMansfield 也许这应该合并到here 中?【参考方案2】:

正如Daniel在评论中所说,std::array的大小被指定为模板参数,因此在运行时无法设置。

您可以通过构造函数参数传递最小容量来构造std::vector

#include <vector>

int main(int argc, char * argv[])

    std::vector<int> a;
    a.reserve(5);
    std::cout << a.capacity() << "\n";
    std::cout << a.size();

    getchar();

但是。 仍然向量的内容将存储在堆上,而不是堆栈上。问题是,编译器必须知道在函数执行之前应该为函数分配多少空间,所以根本不可能在堆栈上存储可变长度数据。

【讨论】:

你所做的并不是真正设置通过构造函数参数的最小容量。它的作用是设置一个初始大小,因为size&lt;=capacity 这有效。设置容量使用reserve @BenjaminBannier 你是对的。有效地达到了目标,但保留的解决方案要优雅得多。 这是基于堆的,这就是我不想要它的原因,并问了我的问题......但是,如果可以实现 std::vector 以在堆栈上分配它的初始容量,并且在第一次重新分配时切换到堆。这对reserve 不起作用,因为它必须在第一次分配时完成……但会很酷。但是我怀疑它在通常的实现中是这样工作的。

以上是关于变长 std::array 像的主要内容,如果未能解决你的问题,请参考以下文章

std::array 实现上的隐式构造函数的奇怪错误

初始化 std::array 的 std::array

使用来自 boost::array 与 std::array 的 std::string::assign 不兼容

为啥 std::array<int, 10> x 不是零初始化但 std::array<int, 10> x = std::array<int, 10>() 似乎是

在基类中引用不同大小的 std::array 而不是 std::array

std::array 是不是有 std::memset 等价物?