std::array 对比阵列性能

std::array vs array performance

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

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

我应该改用 std::array 吗?

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

使用 std::array 与通常的相比有什么优势?它的性能更高吗? copy/access?

更容易处理

std::array 被设计为 C 数组的零开销包装器,赋予它 "normal" 值,就像其他 C++ 容器的语义一样。

您应该不会注意到运行时性能有任何差异,同时您仍然可以享受额外的功能。

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

What are the advantages of using std::array over usual ones?

它具有友好的值语义,因此可以按值传递给函数或从函数返回。它的界面使得查找大小和与基于 STL 样式迭代器的算法一起使用更加方便。

Is it more performant ?

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

Just easier to handle for copy/access ?

是的。

std::array 具有值语义,而原始数组则没有。这意味着您可以复制 std::array 并将其视为原始值。您可以按值或引用作为函数参数接收它们,并且可以 return 按值接收它们。

如果您从不复制 std::array,那么与原始数组没有性能差异。如果您确实需要制作副本,那么 std::array 会做正确的事情并且应该仍然提供同等的性能。

A​​ 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
};

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

Is it more performant ?

It should be exactly the same. By definition, it's a simple aggregate containing an array as its only member.

The situation seems to be more complicated, as std::array does not always produce identical assembly code compared to C-array depending on the specific platform.

I tested this specific situation on 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 and Clang produce identical assembly code for both the C-array version and the std::array version.

MSVC and ICPC, however, produce different assembly code for each array version. (I tested ICPC19 with -Ofast and -Os; MSVC -Ox and -Os)

I have no idea, why this is the case (I would indeed expect exactly identical behavior of std::array and c-array). Maybe there are different optimization strategies employed.

As a little extra: There seems to be a bug in ICPC with

#pragma simd 

for vectorization when using the c-array in some situations (the c-array code produces a wrong output; the std::array version works fine).

Unfortunately, I do not have a minimal working example for that yet, since I discovered that problem while optimizing a quite complicated piece of code.

I will file a bug-report to intel when I am sure that I did not just misunderstood something about C-array/std::array and #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 你应该使用它。