数组与数组性能的比较

如果我想构建一个非常简单的数组,比如:

int myArray[3] = {1,2,3};

我应该使用 std::array代替吗?

std::array<int, 3> a = {{1, 2, 3}};

使用 std::array的优点是什么? 它的性能更好吗? 只是更容易处理复制/访问?

68305 次浏览

std::array被设计为 C 数组的零开销包装器,它提供了类似于其他 C + + 容器语义的“普通”值。

在享受额外特性的同时,您不应该注意到运行时性能的任何差异。

使用 std::array而不是 int[]样式数组是一个好主意,如果你有 C + + 11或增强手头。

使用 std::array的优点是什么?

它具有友好的值语义,因此它可以通过值传递给函数或从函数返回。它的接口使得查找大小更加方便,并且可以与 STL 风格的基于迭代器的算法一起使用。

更有表现力吗?

它应该是完全相同的。根据定义,它是一个包含数组作为其唯一成员的简单聚合。

只是更容易处理复制/访问?

是的。

std::array具有值语义,而原始数组没有。这意味着您可以复制 std::array并将其视为一个基元值。可以通过值或作为函数参数的引用接收它们,也可以通过值返回它们。

如果您从未复制过 std::array,那么与原始数组相比就没有性能差异。如果你确实需要复制,那么 std::array会做正确的事情,仍然应该给予相同的性能。

std::array是围绕 C 样式数组的一个非常薄的包装器,基本上定义为

template<typename T, size_t N>
struct array
{
T _data[N];
T& operator[](size_t);
const T& operator[](size_t) const;
// other member functions and typedefs
};

它是一个 总和,它允许您像使用基本类型一样使用它(例如,您可以通过值传递、赋值等,而标准的 C 数组不能直接赋值或复制到另一个数组)。你应该看看一些标准的实现(从你喜欢的 IDE 跳转到定义,或者直接打开 <array>) ,这是一个非常容易阅读和理解的 C++标准程式库。

更有表现力吗?

它应该是完全相同的。根据定义,它是一个包含数组作为其唯一成员的简单聚合。

情况似乎更加复杂,因为取决于特定的平台,与 C-array 相比,std::array并不总是产生相同的汇编代码。

我在 Godbolt上测试了这个具体情况:

#include <array>
void test(double* const C, const double* const A,
const double* const B, const size_t size) {
for (size_t i = 0; i < size; i++) {
//double arr[2] = {0.e0};//
std::array<double, 2> arr = {0.e0};//different to double arr[2] for some compiler
for (size_t j = 0; j < size; j++) {
arr[0] += A[i] * B[j];
arr[1] += A[j] * B[i];
}
C[i] += arr[0];
C[i] += arr[1];
}
}

GCC 为 C 阵列版本和 std::array版本生成相同的汇编代码。

然而,MSVC ICPC为每个数组版本生成不同的汇编代码。(我用 -Ofast-Os; MSVC -Ox-Os测试 ICPC19)

我不知道为什么会这样(我的确希望 std: : array 和 c-array 的行为完全相同)。也许存在不同的优化策略。

作为小小的额外补充: ICPC 似乎有一个漏洞

#pragma simd

在某些情况下使用 c 数组进行向量化 (c-array 代码产生错误的输出; std::array版本工作正常)。

不幸的是,我还没有一个最小的工作示例来解决这个问题,因为我是在优化一段相当复杂的代码时发现这个问题的。

当我确定我没有误解关于 C-array/std::array#pragma simd的一些东西时,我会向英特尔提交一份错误报告。

您将使用 std::arrayc array获得相同的性能结果 如果运行以下代码:

std::array<QPair<int, int>, 9> *m_array=new std::array<QPair<int, int>, 9>();
QPair<int, int> *carr=new QPair<int, int>[10];
QElapsedTimer timer;
timer.start();
for (int j=0; j<1000000000; j++)
{


for (int i=0; i<9; i++)
{
m_array->operator[](i).first=i+j;
m_array->operator[](i).second=j-i;
}
}
qDebug() << "std::array<QPair<int, int>" << timer.elapsed() << "milliseconds";
timer.start();
for (int j=0; j<1000000000; j++)
{


for (int i=0; i<9; i++)
{
carr[i].first=i+j;
carr[i].second=j-i;
}
}
qDebug() << "QPair<int, int> took" << timer.elapsed() << "milliseconds";
return 0;

你会得到以下结果:

std::array<QPair<int, int> 5670 milliseconds
QPair<int, int> took 5638 milliseconds

Mike Seymour 是对的,如果你能使用 std::array,你就应该使用它。