std::dynarray 与 std::vector

Posted

技术标签:

【中文标题】std::dynarray 与 std::vector【英文标题】:std::dynarray vs std::vector 【发布时间】:2013-10-07 07:24:11 【问题描述】:

C++14 呈现std::dynarray:

std::dynarray 是一个序列容器,它用 尺寸在施工时固定,在整个施工过程中不会改变 对象的生命周期。

std::dynarray 必须与std::vector 一样在运行时分配。

那么std::dynarray 有什么好处和用途,而我们可以使用更具动态性(并且还可以调整大小)的std::vector

【问题讨论】:

@yasouser,不,这与valarray 无关。它是动态的,因为数组的长度是一个运行时值,它不需要在编译时知道,不像std::array 请注意,在上周的 C++ 标准委员会会议上,dynarray 已从 C++14 中删除并放入未来的技术规范(将其视为 TR1 的新版本),因为它具有一些严重的技术问题。 @MM.:首先:目前似乎没有实现——这是一个非常糟糕的迹象,标准委员会学会了不指定未经过良好测试的功能的艰难方法(例如导出,动态异常规范,...)第二:dynarray 在堆栈上分配的事实导致了几个潜在的新陷阱(例如,堆栈空间不足),所有这些都导致未定义的行为,此外还阻止了诸如移动语义之类的优化...在我看来,这似乎是一个隐藏在类似 STL 的层 VLA 后面,有充分的理由在 C++ 中没有采用它。 @LuisMachuca:非常非常非常迟的回复:dynarray 应尽可能进行堆栈分配(如果编译器 + 库支持)并仅使用堆分配 (new[])如果这是不可能的,则作为后备......(例如,当不支持或不适用时) dynarray 不再是 C++14 草案的一部分 【参考方案1】:

那么std::dynarray 有什么好处和用途,什么时候我们可以使用更动态(Re-sizable)的std::vector

dynarrayvector 更小更简单,因为它不需要管理单独的大小和容量值,也不需要存储分配器。

然而,主要的性能优势在于鼓励实现尽可能在堆栈上分配dynarray,避免任何堆分配。例如

std::dynarray<int> d(5);   // can use stack memory for elements
auto p = new std::dynarray<int>(6);  // must use heap memory for elements

这种优化需要编译器的配合,它不能作为纯库类型来实现,而且必要的编译器魔法还没有实现,没有人知道它是多么容易做到。由于缺乏实现经验,上周在芝加哥举行的 C++ 委员会会议上,决定将 std::dynarray 从 C++14 中拉出,并发布单独的数组扩展 TS(技术规范)文档,定义 std::experimental::dynarray 和数组运行时绑定(ARB,类似于 C99 VLA。)这意味着std::dynarray 几乎肯定不会出现在 C++14 中。

【讨论】:

太好了,我想知道在野外是否有任何非平凡的dynarray 实现。我一直认为您需要对现有实践进行两个独立的实现,然后才能有资格进行标准化。 不,没有已知的堆栈分配dynarray 的实现。虽然实施经验非常有用,但并没有规定需要它(但有人会说应该有!) 这里只是头脑风暴,但是创建 2 个函数怎么样:std::dynarray make_dyn_autostorage(int) 和 std::dynarray make_dyn_heap(int)? @KerrekSB,是的,芝加哥的图书馆动议 10 是:“移动我们为计划中的 Array Extensions TS 创建工作论文,删除两篇论文应用于 C++14 CD 的编辑@ 987654321@, "Runtime-sized arrays with automatic storage duration (revision 5)" N3662, "C++ Dynamic Arrays (dynarray)" 并指示 Array Extensions TS 项目编辑器将这些词应用到 Array Extensions Working Paper 作为其初始内容。” @h9uest 这与“C++ 家伙”无关,这些是ISO 技术委员会可交付成果的正式名称,请参阅iso.org/iso/home/standards_development/… 和iso.org/iso/home/standards_development/…【参考方案2】:

正如您自己所说,std::dynarray 用于 固定大小 动态数组。它不可调整大小。粗略地说,它比new T[N]std::unique_ptr&lt;T[]&gt;(new T[N]) 有了改进。

无需调整大小或管理容量意味着您可以实现数据结构的复杂性和空间更少。

此外,std::dynarray 是一种奇怪的动物,它允许实现以不同的、非特定的方式实现它,例如可以将数组放在堆栈上。调用分配函数是“可选的”。你可以指定一个分配器来构造数组的元素,但这不是类型的一部分。

您可能还想知道为什么我们需要std::dynarray 可变长度数组。 C++14 中的 VLA 限制性更强;它们只能是本地的自动变量,无法指定分配策略,当然它们也没有标准的容器接口。


“当前草案”的 23.3.4.2 中的一些示例(以 Google 缓存为例):

explicit dynarray(size_type c);

效果:c 元素分配存储空间。 可能会或可能不会调用全局operator new

template <class Alloc>
dynarray(size_type c, const Alloc& alloc);

效果:除了每个元素都是用uses-allocator构造来构造之外,等价于前面的构造函数。

您是否可以使用给定的分配器来构造数组元素是一个全局特征:

模板 struct uses_allocator, Alloc> : true_type ;

要求: Alloc 应为分配器 (17.6.3.5)。 [注意:此 trait 的特化通知其他库组件 dynarray 可以使用分配器构造,即使它没有嵌套的 allocator_type。]

编辑:乔纳森·韦克利的回答一定会更有权威性和洞察力。

【讨论】:

将分配器传递给dynarray 的构造函数永远不会用于分配,它仅用作元素构造函数的参数(使用“uses-allocator 构造”)。这就是为什么你不能查询是否使用了分配器:因为它从来没有。 @JonathanWakely:啊,我误解了。谢谢,已修复!

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

std::optional<T> 的开销?

如何将 std::accumulate 用于矩阵

c++ 常用功能实现总结

c++ 常用功能实现总结

SWIG 3 中文手册——9. SWIG 库

是否有直接获取 std::vector 元素大小的函数?