118

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

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

我应该std::array改用吗?

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

与通常的相比,使用 std::array 有什么优势?它的性能更高吗?只是更容易处理复制/访问?

4

6 回答 6

138

使用std::array比普通的有什么好处?

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

它的性能更高吗?

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

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

是的。

于 2015-05-15T15:32:09.793 回答
54

Astd::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++ 标准库的一部分,非常易于阅读和理解。

于 2015-05-15T15:40:07.300 回答
30

std::array被设计为 C 数组的零开销包装器,使其具有“正常”值,就像其他 C++ 容器的语义一样。

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

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

于 2015-05-15T15:31:45.240 回答
13

它的性能更高吗?

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

情况似乎更复杂,因为std::array与 C-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];
  }
}

GCCClang为 C 数组版本和版本生成相同的汇编代码std::array

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

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

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

#pragma simd 

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

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

当我确定我不只是误解了有关 C-array/std::array#pragma simd.

于 2018-10-14T18:41:45.250 回答
12

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

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

于 2015-05-15T15:33:08.800 回答
0

如果您运行以下代码std::array,您将获得相同的性能结果:c 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你就应该用它。

于 2021-10-01T05:47:48.837 回答