std::array
значительно превосходит C-массивы. И даже если я хочу взаимодействовать с устаревшим кодом, я могу просто использовать std::array::data()
. Есть ли какая-нибудь причина, по которой мне когда-либо понадобился массив старой школы?
Теперь, когда у нас есть std:: array, какие применения остаются для массивов в стиле C?
Ответ 1
Если я что-то пропустил (я не следил за последними изменениями в стандарте слишком близко), большинство применений массивов стиля C все еще остаются. std::array
разрешает статическую инициализацию, но она все равно не будет считать инициализаторы для вас. И поскольку единственное реальное использование массивов стилей C до std::array
было для статически инициализированных таблиц
вдоль линий:
MyStruct const table[] =
{
{ something1, otherthing1 },
// ...
};
используя обычные функции шаблона begin
и end
(принятые в
С++ 11), чтобы перебирать их. Не упоминая размер, который компилятор определяет из числа инициализаторов.
EDIT: Еще одна вещь, которую я забыл: строковые литералы по-прежнему представляют собой массивы стиля C; то есть с типом char[]
. Я не думаю, что кто-то исключил бы использование строковых литералов только потому, что у нас есть std::array
.
Ответ 2
Нет. Это, конечно, прямо. И в 30 символах.
Конечно, вам нужны C-массивы для реализации std::array
, но это не повод для того, чтобы пользователь когда-либо захотел использовать C-массивы. Кроме того, no, std::array
не менее эффективен, чем массив C, и имеет возможность для ограниченного доступа. И, наконец, вполне разумно, чтобы любая программа на С++ зависела от стандартной библиотеки, а именно, если она не имеет доступа к стандартной библиотеке, то ваш компилятор является несоответствующим, а вопрос помечен как "С++", а не "С++ и те не-С++ вещи, которые пропускают половину спецификации, потому что считают, что это неуместно".
Ответ 3
Похоже, что использование многомерных массивов проще с массивами C, чем std::array
. Например,
char c_arr[5][6][7];
в отличие от
std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;
Также из-за свойства автоматического распада массивов C, c_arr[i]
в приведенном выше примере будет распадаться на указатель, и вам просто нужно передать оставшиеся измерения в качестве еще двух параметров. Могу сказать, что c_arr
не дорого стоит копировать. Однако cpp_arr[i]
будет очень дорого копировать.
Ответ 4
Как сказал Сумант, многомерные массивы намного проще использовать со встроенными C-массивами, чем с std::array
.
При вложенности, std::array
может стать очень трудным для чтения и излишне подробного.
Например:
std::array<std::array<int, 3>, 3> arr1;
по сравнению с
char c_arr[3][3];
Также обратите внимание, что begin()
, end()
и size()
все возвращают бессмысленные значения, когда вы в гнезде std::array
.
По этим причинам я создал свои собственные контейнеры с многомерными массивами фиксированного размера, array_2d
и array_3d
. Они аналогичны std::array
, но для многомерных массивов 2 и 3 измерений. Они более безопасны и имеют худшую производительность, чем встроенные многомерные массивы. Я не включил контейнер для многомерных массивов с размерами больше 3, поскольку они являются необычными. В С++ 0x может быть выполнена версия вариационного шаблона, которая поддерживает произвольное количество измерений.
Пример двумерного варианта:
//Create an array 3 x 5 (Notice the extra pair of braces)
fsma::array_2d <double, 3, 5> 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
Вы можете скачать библиотеку здесь:
Ответ 5
Макеты C-стиля, доступные на С++, на самом деле гораздо менее универсальны, чем реальные C-массивы. Разница в том, что в C типы массива могут иметь размеры времени выполнения. Ниже приведен допустимый код C, но он не может быть выражен с помощью массивов С++ C-style или типов С++ array<>
:
void foo(int bar) {
double tempArray[bar];
//Do something with the bar elements in tempArray.
}
В С++ вам нужно будет выделить временный массив в куче:
void foo(int bar) {
double* tempArray = new double[bar];
//Do something with the bar elements behind tempArray.
delete[] tempArray;
}
Это невозможно с помощью std::array<>
, потому что bar
не известно во время компиляции, для этого требуется использование либо массивов C-стиля в С++, либо std::vector<>
.
Хотя первый пример можно относительно легко выразить в С++ (хотя и требует new[]
и delete[]
), в С++ без 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. Типичная реализация манипуляции с изображениями на С++ Пример будет выглядеть следующим образом:
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.
Ответ 6
Может быть, std::array
не медленный. Но я сделал некоторый бенчмаркинг, используя простой магазин и прочитанный из std:: array;
См. Приведенные ниже результаты тестов (на W8.1, обновление VS2013 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 ( ссылка)
Код класса тестов здесь;
Я не знаю много о бенчмарках... Мой код может быть ошибочным
Ответ 7
- реализовать что-то вроде
std::array
- если вы не хотите использовать STL или не можете
- Для производительности