Подтвердить что ты не робот

Замените массивы с фиксированным размером на std:: array?

Работая с устаревшим кодом, я спросил себя, должен ли я заменить массивы C-стиля фиксированного размера на новый std:: array? E. g.

static const int TABLE_SIZE = 64;
double table[TABLE_SIZE];

заменить

std::array<double, TABLE_SIZE> table;

Пока я вижу преимущества использования std::vector для массивов с переменным размером, я не вижу их с фиксированным размером. table.size() известно в любом случае, std::begin(), std::end(), поскольку свободные функции могут быть использованы для STL-алгоритмов с массивами в стиле C. Таким образом, помимо того, что я более стандартно согласен, не хватает ли я большего количества преимуществ? Стоит ли работа заменить все случаи или считается лучшей практикой?

4b9b3361

Ответ 1

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

Еще одна особенность: они могут рассматриваться как кортежи, поскольку они предоставляют функции доступа, подобные типу.

Последнее, но не менее важное: user2079303 заметил: если ваш код будет использоваться новичками-программистами, он может предотвратить процесс разложения массива при передаче его в качестве аргумента.

Если вам интересно, следует ли просто заменить все ваши массивы C-стиля на std:: arrays, ответ будет да, если вы собираетесь использовать некоторые из недавно доступных функций и/или переписать часть своего кода чтобы воспользоваться этими возможностями. Если вы просто замените C-массивы на std:: arrays (не трогая ничего другого), это может не стоить того.

Ответ 2

Есть еще одна вещь, о которой я еще не упоминал: std::array::at(). Повреждения стека могут быть очень неприятными для отладки, а ошибки из-за повреждения стека могут скрыть в течение длительного времени.: (Ситуация стала несколько лучше с Адрес Sanitizer. Тем не менее, я предпочитаю связать проверку дезинфицирующего средства по адресу.

По-моему, доступ к элементам с ограниченным доступом является достаточной причиной для использования std::array, а не массивов стилей C.

Ответ 3

Дополнительная функция, которая имеет std::array, состоит в том, что она может быть назначена для копирования;

std::array<int, 3> a = {1, 2, 3};
std::array<int, 3> b = {4, 5, 6};

std::array<int, 3> c = a;         // copy-construction
a = b;                            // copy-assignment

Ответ 4

ИМХО, вы никогда не должны менять рабочий, устаревший код без по-настоящему веской причины. Если вы разрабатываете усовершенствование или исправляете ошибку, и файлы, о которых идет речь, все равно будут изменены, тогда я бы сказал, что обязательно сделайте это. В противном случае у вас, вероятно, будут лучшие вещи, связанные с вашим временем. Всегда существует риск, связанный с изменением исходного кода, который может привести к длительной отладке времени, когда вы могли бы делать более продуктивные вещи.

Ответ 5

Это зависит от варианта использования. Производительность и по площади, они должны быть идентичными, за исключением члена размера, который std::array несет. EDIT: Даже размер будет оптимизирован. Так что это идентично даже пространственно. Реализации обычно могут выполнять:

template <class T, std::size_t N>
class array {
...
public:
    contsexpr std::size_t size() const { return N; }

}

И избегайте хранения размера строки.

std::array<T, N> не будет распадаться на указатель при его прохождении. Но в вашем случае использования у вас есть глобальная переменная, я думаю. Я бы не изменил то, что он уже работает, чтобы сделать его более приятным.

С другой стороны, если вы хотите передать std::array любого размера функции, вам нужно будет его шаблон:

template <std::size_t N>
void f(std::array<MyT, N> const & arr);

Плюсы std::array

  • Безопаснее, они не распадаются на указатели.
  • Они несут размер.

Минусы std::array

  • Если вы хотите, чтобы общая функция выполняла std::array, вам нужно будет сделать это в заголовке в качестве шаблона.

В массивах C вы можете сделать это:

void f(MyT const * arr, std::size_t size);

и он будет работать с любым массивом, независимо от его длины. Это менее безопасно, но более удобно скрывать зависимости в .cpp файлы, так как позже вы можете закодировать функцию внутри .cpp файла.

Но, как я уже сказал, с учетом вашего варианта использования, выберите. Я бы не стал изменить код, который работает и не будет выставлен (например, если он глобальный, который никогда не воспринимается как параметр в функциях) любым опасным способом.

Ответ 6

Я думаю, std:: array имеет много преимуществ перед массивами c-style. Поэтому стоит заменить все вхождения или по крайней мере начать использовать std:: array вместо c-style. Для получения дополнительной информации мы можем посмотреть здесь, упомянутый в С++ 11 FAQ от Bjarne Stroustrup.

  • У него нет лишних накладных расходов, кроме того, что нужно для хранения его элементов.
  • Он не использует бесплатный магазин, и его можно инициализировать с помощью списка инициализаторов
  • Он знает свой размер (количество элементов).
  • Он не конвертируется в указатель, если вы явно не задаете его.
  • Стандартные функции массива делают его привлекательным для программирования встроенных систем (и аналогичных ограничений, критически важных для производительности или критически важных для безопасности задач).

Другими словами, это очень похоже на встроенный массив без проблем.

Относительно вашей точки в table.size() известно, но она действительна только в том случае, если кто-то использует массив в контексте, где он был определен. Если нам нужно передать его какой-либо другой функции, то это неизвестно, и нам пришлось пройти его.

Ответ 7

Есть куча вещей:

  • поэтому он выглядит как любая другая последовательность в стандартной библиотеке
  • tuple, как доступ (get, tuple_size, tuple_element) с доступом к времени с проверкой времени компиляции
  • не распадается на указатель

Первый момент довольно очевиден и в основном выгоден в общем коде. Второй момент немного неясен: из семантического arrayS есть не что иное, как вырожденный tupleS (конечно tupleS не гарантирует последовательного хранения в памяти). Рассмотрение их как таковое имеет смысл, и код, работающий с кортежами, может работать в основном с массивами. Третий момент - хороший бонус и добавляет немного безопасности для кода.