std::array против производительности массива

Если я хочу построить очень простой массив, например

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

Должен ли я использовать std::array вместо этого?

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

В чем преимущества использования std::array перед обычными? Он более производительный? Просто проще обрабатывать для копирования/доступа?


person Arcyno    schedule 15.05.2015    source источник
comment
определение многомерного массива с помощью std:: будет затруднено   -  person goGud    schedule 15.05.2015
comment
@goGud: Не сложно, просто более подробно.   -  person Mike Seymour    schedule 15.05.2015
comment
Распад указателя, получение ссылки и т. д., многие вещи странны в c-массивах. Итератор может быть указателем в случае c-массивов, а for (auto i = ++std::begin(myArray); . . . может даже не компилироваться (похоже, что временные массивы фундаментального типа не изменяемы, по крайней мере, не с clang 6)   -  person Patrick Fromberg    schedule 13.05.2018
comment
Инициализация тоже волшебным образом отличается: 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)   -  person BitTickler    schedule 09.10.2019
comment
Почему двойные скобки в инициализации std::array?   -  person Marc.2377    schedule 09.12.2019
comment
@Marc.2377 std::array - это просто оболочка для массивов в стиле C. Если я не ошибаюсь, в некоторых более ранних версиях C++ вы не могли инициализировать его одинарными скобками. Однако не верьте мне на слово, так как я не использовал их много   -  person H-005    schedule 20.07.2020


Ответы (5)


Какие преимущества использования std::array перед обычными?

Он имеет дружественную семантику значений, поэтому его можно передавать в функции или возвращать из них по значению. Его интерфейс упрощает определение размера и использование с алгоритмами на основе итераторов в стиле STL.

Он более производительный?

Он должен быть точно таким же. По определению это простой агрегат, содержащий массив в качестве единственного члена.

Просто проще обрабатывать для копирования/доступа?

да.

person Mike Seymour    schedule 15.05.2015

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++, которую довольно легко читать и понимать.

person vsoftco    schedule 15.05.2015
comment
Незначительное исправление, в документах это определено как структура: en.cppreference.com/w/ cpp/контейнер/массив - person Overt_Agent; 26.07.2021
comment
@Overt_Agent Спасибо, исправлено (хотя у class...{public:...} были те же правила доступа, что и у структуры;) - person vsoftco; 26.07.2021

std::array разработан как оболочка с нулевыми издержками для массивов C, которая придает ему "нормальное" значение, подобное семантике других контейнеров C++.

Вы не должны заметить никакой разницы в производительности во время выполнения, пока вы все еще можете пользоваться дополнительными функциями.

Использование массивов в стиле std::array вместо int[] — хорошая идея, если у вас есть C++11 или boost.

person Baum mit Augen    schedule 15.05.2015

Он более производительный?

Он должен быть точно таким же. По определению это простой агрегат, содержащий массив в качестве единственного члена.

Ситуация кажется более сложной, так как 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];
  }
}

GCC и Clang создают идентичный ассемблерный код как для версии C-массива, так и для версии std::array.

Однако MSVC и ICPC создают разные ассемблерные коды для каждой версии массива. (Я протестировал ICPC19 с -Ofast и -Os; MSVC -Ox и -Os)

Я понятия не имею, почему это так (я действительно ожидал бы точно такого же поведения std::array и c-array). Возможно, используются разные стратегии оптимизации.

В качестве небольшого дополнения: кажется, в ICPC есть ошибка с

#pragma simd 

для векторизации при использовании c-массива в некоторых ситуациях (код c-массива выдает неправильный вывод; версия std::array работает нормально).

К сожалению, у меня пока нет минимального рабочего примера для этого, так как я обнаружил эту проблему при оптимизации довольно сложного фрагмента кода.

Я отправлю отчет об ошибке в Intel, когда буду уверен, что не просто неправильно понял что-то о C-array/std::array и #pragma simd.

person Henryk    schedule 14.10.2018
comment
можно считать ошибкой компилятора? - person OznOg; 14.10.2018

std::array имеет семантику значений, а необработанные массивы - нет. Это означает, что вы можете скопировать std::array и обращаться с ним как с примитивным значением. Вы можете получить их по значению или ссылке в качестве аргументов функции и можете вернуть их по значению.

Если вы никогда не копируете std::array, то нет никакой разницы в производительности по сравнению с необработанным массивом. Если вам нужно делать копии, то std::array будет делать то, что нужно, и по-прежнему будет давать одинаковую производительность.

person b4hand    schedule 15.05.2015