std::array
значительно превосходит массивы C. И даже если я хочу взаимодействовать с устаревшим кодом, я могу просто использовать std::array::data()
. Есть ли причина, по которой мне когда-либо понадобится массив старой школы?
источник
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
.
const char[]
Нет. Говоря прямо. И в 30 символах.
Конечно, вам нужны массивы C для реализации
std::array
, но на самом деле это не причина, по которой пользователю когда-либо понадобятся массивы C. Кроме того, нет,std::array
он не менее производительный, чем массив C, и имеет возможность доступа с проверкой границ. И, наконец, для любой программы на C ++ вполне разумно зависеть от стандартной библиотеки - в этом смысле она является стандартной - и если у вас нет доступа к стандартной библиотеке, то ваш компилятор не соответствует требованиям и вопрос помечен как «C ++», а не «C ++ и те вещи, которые не относятся к C ++, которые пропускают половину спецификации, потому что считают это неуместным».источник
std::array
в автономной реализации C ++ 11.Похоже, что с массивами 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]
копирование будет очень затратным.источник
array
функции без потери размеров. И если вы передадите его в шаблон функции, то эта функция сможет вывести как размер, так и размер каждого измерения или только одно из них. Это может быть интересно для научных библиотек шаблонов, которые в основном работают с произвольными измерениями.template <typename T, int M, int N> using array2d = std::array<std::array<T, N>, M>;
должен решить любую из этих проблем.c_arr
является очень дорогим для копирования! Для этого вы должны предоставить код самостоятельно. Указатель, на который он будет распадаться, является более близким эквивалентом ссылки, чем копия, и вы можете использовать егоstd::array
для передачи ссылки, если это то, что вы хотите.std::size_t
вместо этогоint
? извините за придирки, но это сделало бы его универсальным.size_t
если хотите, хотя я не могу представить, что существует множество сценариев, в которых необходимы массивы с более чем 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, поскольку они необычны. В C ++ 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
Вы можете скачать библиотеку здесь:
http://fsma.googlecode.com/files/fsma.zip
источник
arr[x][y]
вы не можете сказать,arr
является ли это массивом массивов, массивом указателей, указателем на массив или указателем на указатель; все для реализации законны, в зависимости от ваших потребностей. И, вероятно, в большинстве реальных случаев использования многомерных массивов размер необходимо определять во время выполнения.Массивы в стиле C, доступные в C ++, на самом деле гораздо менее универсальны, чем настоящие массивы C. Разница в том, что в C типы массивов могут иметь размеры во время выполнения . Ниже приведен допустимый код C, но он не может быть выражен ни с помощью массивов C-стиля C ++, ни с помощью
array<>
типов C ++ :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.
источник
gcc
например). C11 сделал довольно много интересных вещей необязательными, и я не думаю, что это потому, что они хотят объявить эту функцию вне закона. Я склонен рассматривать это как знак того, что они хотели снизить уровень написания полностью совместимого со стандартами компилятора: VLA довольно сложно реализовать, и большая часть кода может обойтись без него, поэтому имеет смысл для нового компилятора на некоторых новых платформу, чтобы не нужно было сразу внедрять VLA.Может быть,
std::array
не медленный. Но я провел несколько тестов, используя простое сохранение и чтение из массива std :: array; См. Результаты теста ниже (на W8.1, обновление 4 VS2013):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 ( ссылка )
Код тестового класса здесь ;
Я не очень разбираюсь в тестах ... Мой код может быть некорректным
источник
long test_arr_without_init() { return ARR_SIZE; }
void test_arr_without_init() {}
настоящее. Вам действительно нужно перепрыгнуть через обручи, чтобы убедиться, что код, который вы измеряете, является кодом, который вы хотите измерить.std::array
источник
std::array
будет менее производительно, чем массив C.at()
, это не такoperator[]
, просто какstd::vector
. Нет никакого снижения производительности или раздувания кодаstd::array
, компилятор предназначен для оптимизации такого рода вещей. И, конечно же, добавление проверенной функции - отличный инструмент для отладки и большое преимущество. @Lou Franco: Весь код C ++ может зависеть от стандартной библиотеки - вот для чего она нужна. @Earlz: Если у вас нет STL, значит, это не C ++, и на этом все.std::array
его больше, чем эквивалентное использование массива C.