std :: array vs数组性能


84

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

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

我应该std::array改用吗?

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

与常规方法相比,使用std :: array有什么优势?表现更好吗?只是更易于处理以进行复制/访问?


2
使用std ::定义多维数组将很困难
goGud 2015年

15
@goGud:不难,只是更冗长。
Mike Seymour

1
指针衰减,参考等...,关于c数组的很多事情都很奇怪。在使用c数组的情况下,迭代器可能是一个指针,for (auto i = ++std::begin(myArray); . . . 甚至可能无法编译(看来基本类型的临时对象是不可变的,至少对于clang 6而言不是这样)
Patrick Fromberg,

初始化也有很大的不同:struct Direction { int32_t dw; int32_t dh; };static const Direction DIRECTIONS[DIRECTIONS_COUNT] { { -1, 1}, {0,1}, {1,1} , { 1, 0 }, {1,-1}, {0,-1} , {-1,-1}, {-1,0} };编译。但是,如果更改为std::array<Direction,DIRECTIONS_COUNT>具有相同初始化程序列表的,突然会收到“太多初始化程序”错误。(VS 2019社区,语言= C ++ 17)
BitTickler

为什么在std::array初始化中使用双括号?
Marc.2377 '19

Answers:


101

std::array与通常相比,使用有什么好处?

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

表现更好吗?

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

只是更易于处理以进行复制/访问?

是。


41

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

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

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


24

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

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

如果您手边有C ++ 11或boost,那么最好使用std::array而不是int[]样式数组。


10

表现更好吗?

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

这种情况似乎更加复杂,因为std::array根据特定平台,与C阵列相比,并非总是产生相同的汇编代码。

我在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-array版本和std::array版本生成相同的汇编代码。

但是,MSVCICPC对于每个阵列版本都会产生不同的汇编代码。(我用-Ofast-Os; MSVC-Ox和测试了ICPC19 -Os

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

还有一点:ICPC中似乎有一个错误

#pragma simd 

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

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

当我确定我不只是误解了C-array /std::array和的内容时,我将向英特尔提交错误报告#pragma simd


1
可以视为编译器错误?
OznOg

8

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.