Теперь, когда у нас есть std :: array, какие применения остаются для массивов в стиле C?

std::array значительно превосходит массивы C. И даже если я хочу взаимодействовать с устаревшим кодом, я могу просто использовать std::array::data() . Есть ли какая-нибудь причина, по которой мне когда-либо понадобился массив старой школы?

Если я что-то пропустил (я не следил за последними изменениями в стандарте слишком близко), большинство применений массивов стиля C все еще остаются. std::array разрешает статическую инициализацию, но он все равно не будет считать инициализаторы для вас. И поскольку единственное реальное использование массивов стилей C до того, как std::array было для статически инициализированных таблиц в строках:

 MyStruct const table[] = { { something1, otherthing1 }, // ... }; 

используя обычные функции begin и end шаблонов (принятые в C ++ 11), чтобы перебирать их. Без упоминания размера, который компилятор определяет из числа инициализаторов.

EDIT: Еще одна вещь, которую я забыл: строковые литералы по-прежнему представляют собой массивы стиля C; т.е. с типом char[] . Я не думаю, что кто-то исключил бы использование строковых литералов только потому, что у нас есть std::array .

Нет. Это, конечно, грубо. И в 30 символов.

Конечно, вам нужны C-массивы для реализации std::array , но на самом деле это не причина того, что пользователь когда-либо захочет использовать C-массивы. Кроме того, no, std::array не менее эффективен, чем массив C, и имеет возможность для ограниченного доступа. И, наконец, вполне разумно, чтобы любая программа на C ++ зависела от стандартной библиотеки, и это означает, что она стандартная, и если у вас нет доступа к стандартной библиотеке, то ваш компилятор является несоответствующим, а вопрос помечен как «C ++», а не «C ++ и те не-C ++ вещи, которые пропускают половину спецификации, потому что они считают это неуместным».

Похоже, что использование многомерных массивов проще с массивами C, чем с std::array . Например,

 char c_arr[5][6][7]; 

в отличие от

 std::array, 6>, 5> cpp_arr; 

Кроме того, из-за свойства автоматического распада массивов C, c_arr[i] в приведенном выше примере будет распадаться на указатель, и вам просто нужно передать оставшиеся измерения в качестве еще двух параметров. c_arr что c_arr не дорого копировать. Однако cpp_arr[i] будет очень дорогостоящим для копирования.

Как сказал Сумант, многомерные массивы намного проще использовать со встроенными C-массивами, чем с std::array .

Когда вложен, std::array может стать очень трудным для чтения и излишне подробным.

Например:

 std::array, 3> arr1; 

в сравнении с

 char c_arr[3][3]; 

Также обратите внимание, что begin() , end() и size() возвращают бессмысленные значения, когда вы вставляете std::array .

По этим причинам я создал свои собственные контейнеры многомерного массива фиксированного размера, array_2d и array_3d . Они аналогичны std::array но для многомерных массивов размером 2 и 3. Они более безопасны и имеют худшую производительность, чем встроенные многомерные массивы. Я не включил контейнер для многомерных массивов с размерами больше 3, поскольку они являются необычными. В C ++ 0x может быть выполнена версия вариационного шаблона, которая поддерживает произвольное количество измерений.

Пример двумерного варианта:

 //Create an array 3 x 5 (Notice the extra pair of braces) fsma::array_2d  my2darr = {{ { 32.19, 47.29, 31.99, 19.11, 11.19}, { 11.29, 22.49, 33.47, 17.29, 5.01 }, { 41.97, 22.09, 9.76, 22.55, 6.22 } }}; 

Полная документация доступна здесь:

http://fsma.googlecode.com/files/fsma.html

Вы можете скачать библиотеку здесь:

http://fsma.googlecode.com/files/fsma.zip

Матрицы C-стиля, доступные на C ++, на самом деле гораздо менее универсальны, чем реальные C-массивы. Разница в том, что в C типы массива могут иметь размеры времени выполнения . Ниже приведен допустимый код C, но он не может быть выражен с помощью массивов C ++ C-style или array<> типов C ++ array<> :

 void foo(int bar) { double tempArray[bar]; //Do something with the bar elements in tempArray. } 

В C ++ вам нужно будет выделить временный массив в куче:

 void foo(int bar) { double* tempArray = new double[bar]; //Do something with the bar elements behind tempArray. delete[] tempArray; } 

Это невозможно сделать с помощью std::array<> , потому что во время компиляции bar не известна, она требует использования либо массивов C-стиля в C ++, либо std::vector<> .


Хотя первый пример можно относительно легко выразить в C ++ (хотя и требуя new[] и delete[] ), в C ++ без std::vector<> не может быть достигнуто следующее:

 void smoothImage(int width, int height, int (*pixels)[width]) { int (*copy)[width] = malloc(height*sizeof(*copy)); memcpy(copy, pixels, height*sizeof(*copy)); for(y = height; y--; ) { for(x = width; x--; ) { pixels[y][x] = //compute smoothed value based on data around copy[y][x] } } free(copy); } 

Дело в том, что указатели на линейные массивы int (*)[width] не могут использовать ширину времени выполнения в C ++, что делает код обработки изображений более сложным в C ++, чем в C. Типичная реализация изображения на C ++ пример манипуляции будет выглядеть так:

 void smoothImage(int width, int height, int* pixels) { int* copy = new int[height*width]; memcpy(copy, pixels, height*width*sizeof(*copy)); for(y = height; y--; ) { for(x = width; x--; ) { pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x] } } delete[] copy; } 

Этот код выполняет точно такие же вычисления, как и код C выше, но он должен выполнять вычисление индекса вручную, где бы ни были использованы индексы . Для 2D-случая это по-прежнему возможно (даже при том, что оно имеет множество возможностей для неправильного вычисления индекса). Тем не менее, это действительно неприятно в 3D-случае.

Мне нравится писать код на C ++. Но всякий раз, когда мне нужно манипулировать многомерными данными, я действительно спрашиваю себя, должен ли я переместить эту часть кода на C.

Может быть, std::array не медленный. Но я сделал некоторый бенчмаркинг, используя простой магазин и прочитанный из std :: array; См. Приведенные ниже результаты тестов (на W8.1, VS2013 Update 4):

 ARR_SIZE: 100 * 1000 Avrg = Tick / ARR_SIZE; test_arr_without_init ==>VMem: 5.15Mb ==>PMem: 8.94Mb ==>Tick: 3132 ==>Avrg: 0.03132 test_arr_with_init_array_at ==>VMem: 5.16Mb ==>PMem: 8.98Mb ==>Tick: 925 ==>Avrg: 0.00925 test_arr_with_array_at ==>VMem: 5.16Mb ==>PMem: 8.97Mb ==>Tick: 769 ==>Avrg: 0.00769 test_c_arr_without_init ==>VMem: 5.16Mb ==>PMem: 8.94Mb ==>Tick: 358 ==>Avrg: 0.00358 test_c_arr_with_init ==>VMem: 5.16Mb ==>PMem: 8.94Mb ==>Tick: 305 ==>Avrg: 0.00305 

Согласно отрицательным знакам, код, который я использовал, находится в pastebin ( link )

Здесь приведен код базового classа;

Я не очень разбираюсь в бенчмарках … Мой код может быть ошибочным

  1. реализовать что-то вроде std::array
  2. если вы не хотите использовать STL или не можете
  3. Для производительности
  • C ++ STL vector vs array в реальном мире
  • Как определить массив указателей функций в C
  • Макет в памяти структуры. структура массивов и массив структур в C / C ++
  • Malloc 3-мерный массив в C?
  • Android - настроить Spinner для использования массива
  • Преобразование массива объектов в массив их примитивных типов
  • Как лучше всего обрабатывать динамические многомерные массивы в C / C ++?
  • Можно ли рассматривать 2D-массив как непрерывный массив 1D?
  • Как создать точную копию массива?
  • Использование массива нулевой длины
  • Самый быстрый алгоритм для массива размера круга N для M позиции
  • Давайте будем гением компьютера.