变长 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<=capacity
这有效。设置容量使用reserve
。
@BenjaminBannier 你是对的。有效地达到了目标,但保留的解决方案要优雅得多。
这是基于堆的,这就是我不想要它的原因,并问了我的问题......但是,如果可以实现 std::vector
以在堆栈上分配它的初始容量,并且在第一次重新分配时切换到堆。这对reserve
不起作用,因为它必须在第一次分配时完成……但会很酷。但是我怀疑它在通常的实现中是这样工作的。以上是关于变长 std::array 像的主要内容,如果未能解决你的问题,请参考以下文章
使用来自 boost::array 与 std::array 的 std::string::assign 不兼容
为啥 std::array<int, 10> x 不是零初始化但 std::array<int, 10> x = std::array<int, 10>() 似乎是