c++11 std::array vs 静态数组 vs std::vector

Posted

技术标签:

【中文标题】c++11 std::array vs 静态数组 vs std::vector【英文标题】:c++11 std::array vs static array vs std::vector 【发布时间】:2013-09-18 09:42:43 【问题描述】:

第一个问题,如果我要为接下来的 3 年开发代码,开始使用 c++11 是不是一件好事?

如果是的话,如果我想将它与 Lapack 一起使用,那么实现矩阵的“最佳”方法是什么?我的意思是,做std::vector<std::vector< Type > > Matrix 不容易与 Lapack 兼容。

到目前为止,我用Type* Matrix(new Type[N]) 存储了我的矩阵(newdelete 的指针形式很重要,因为数组的大小不是像 5 这样的数字,而是作为变量给出)。

但是在 C++11 中可以使用 std::array。根据这个site,这个容器似乎是最好的解决方案……你怎么看?

【问题讨论】:

请一次一个问题。 @KerrekSB :嗯,我知道,但第一个问题是是/否问题...... gist.github.com/rmartinho/3959961 @PinkFloyd:第一个问题会因为“主要基于意见”而立即结束,第二个技术问题会得到更多关注。将这两者混合起来会给你一个令人反感的平庸问题,人们可能会跳过。 @R.MartinhoFernandes 实际上,我用 c++03 为我的矩阵编写了或多或少完全相同的代码。但我很难对其进行排序。这就是为什么我考虑使用 c++11 并且可能使用 c++11 std::array 而不是指针 【参考方案1】:

首先,如果您要学习 C++,请学习 C++11。之前的 C++ 标准于 2003 年发布,这意味着它已经有 10 年的历史了。这在 IT 世界中很多。 C++11 技能也将顺利转化为即将推出的 C++1y(很可能是 C++14)标准。

std::vectorstd::array 之间的主要区别在于动态(在大小和分配方面)和静态存储。因此,如果您想要一个始终为 4x4 的矩阵类,std::array<float, 4*4> 就可以了。

这两个类都提供.data() 成员,它应该产生一个兼容的指针。但是请注意,std::vector<std::vector<float>> 不会占用连续的16*sizeof(float) 内存(所以v[0].data() 不会 工作)。如果您需要动态大小的矩阵,请使用单个 vector 并将其调整为 width*height 大小。

由于对元素的访问会有点困难(v[width * y +x]v[height * x + y]),您可能需要提供一个包装类,允许您按行/列对访问任意字段。

由于您还提到了 C 风格的数组; std::array 提供了更好的接口来处理相同类型的存储,因此应该是首选; std::array 上的静态数组没有任何好处。

【讨论】:

感谢您的完整回答。但是您的最后一句话似乎不同意“结构将 C 样式数组的性能和可访问性与标准容器的优点相结合,例如知道自己的大小、支持分配、随机访问迭代器等。” (请参阅我给我的问题的链接) 到底有什么不同?我认为它的含义几乎相同。 在我看来,它们暗示其他容器(即 std::vector)不如 C 样式数组高效,但 std::array 是......但我不知道足以比较C风格数组std::vectorstd::array的效率。 std::vector 由于其动态特性而具有(非常轻微的)性能影响;因为所需内存的大小在编译时是未知的,所以必须调用 OS 内存分配。 C 风格的数组和std::array 是固定大小的OTOH,因此可以在堆栈上分配它们而无需向操作系统请求更多内存。两种方法对元素的访问都同样快,归结为简单的指针运算。如果您那么对性能很认真,您可能应该使用 SIMD 指令和类型来利用硬件加速计算。 如果 std::array 是静态分配的(即在数据部分中;通过在任何函数外部声明它或在函数内部使用 static 关键字),那么它的地址不会在编译时间,允许一些优化(即不需要取消引用指针)?所以应该更快?【参考方案2】:

这是对这个问题的一个很晚的回复,但如果有人读到这个,我只想指出,几乎永远不应该将矩阵实现为“向量的向量”。原因是矩阵的每一行都存储在堆上的某个随机位置。这意味着矩阵运算将执行大量随机内存访问,从而导致缓存未命中,从而大大减慢了实现速度。

换句话说,如果您关心性能,只需分配一个大小为rows * columnsarray/std::array/std::vector,然后使用包装函数将一对整数转换为数组中的相应元素。除非您需要支持返回对矩阵行的引用之类的功能,否则所有这些选项都应该可以正常工作。

【讨论】:

@DOUGLASO.MOEN 这完全取决于堆的争用程度。如果您只是直接分配了一个向量向量,而没有任何其他尝试分配(或释放一个),则缓冲区很可能一个接一个地结束。 std::vector<std::array<T, RowSize>> 更方便,与带包装的扁平行*列一样快

以上是关于c++11 std::array vs 静态数组 vs std::vector的主要内容,如果未能解决你的问题,请参考以下文章

如何声明指向 C++11 std::array 的指针?

C++ STL应用与实现5: 如何使用std::array (since C++11)

C ++ 11中的数组[重复]

C ++初始化对象的非静态成员数组

C++11数组了解

如何静态断言 std::array 成员的大小