std ::数组与数组性能



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

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

我应该使用 std::array吗?

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

使用std::array比通常的优点是什么?表现更多吗?更容易处理复制/访问?

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

它具有友好的价值语义,因此可以按值传递给或从功能中返回。它的界面使查找尺寸并与基于STL风格的算法更加方便。

它的性能更多吗?

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

更容易处理/访问?

是。

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

它是一个聚合,它允许您几乎像基本类型一样使用它(即,您可以通过价值传递,分配等,而标准C数组不能直接分配或直接复制到另一个数组)。您应该查看某些标准实现(从您喜欢的IDE或直接打开<array>),它是C 标准库中的一部分,非常容易阅读和理解。

std::array被设计为c阵列的零交叉包装器,它像其他c 容器的语义一样为"正常"值。

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

使用std::array代替int[]样式数组是一个好主意,如果您有C 11或提升。

它的性能更多吗?

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

这种情况似乎更为复杂,因为与特定平台相比,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 clang 为C-array版本和std::array版本制作相同的汇编代码。

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

我不知道,为什么是这种情况(我确实期望STD :: Array和C-Array完全相同的行为)。也许采用了不同的优化策略。

额外一点:ICPC中似乎有一个错误

#pragma simd 

在某些情况下使用C阵列时进行矢量化(C阵列代码产生错误的输出; std::array版本正常)。

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

当我确定我不仅误解了有关C-Array/std::array#pragma simd的某些内容时,我会向英特尔提出错误报告。

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

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

您将使用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,则应使用它。

虽然std::array具有一些优点,如其他有用的答案中所述,有些人陈述了"……没有比原始数组的性能差异。

这根本不是真实的,并且对从事真正嵌入式开发(时间关键,裸机)的任何人都有误导。

使用以50MHz(CPU)运行的STM32G0B1快速而肮脏的测试:写入std::array比原始C样式数组的时间长约5 µs。对我来说,这是一个重大的性能差异。

最新更新