Теперь, когда у нас есть std :: array, что осталось использовать для массивов в стиле C? - PullRequest
85 голосов
/ 24 мая 2011

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

Ответы [ 7 ]

59 голосов
/ 24 мая 2011

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

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

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

РЕДАКТИРОВАТЬ: Еще одна вещь, которую я забыл: строковые литералы все еще являются массивами в стиле C; то есть с типом char[]. Я не думаю, что кто-то исключит использование строковых литералов только потому, что у нас есть std::array.

29 голосов
/ 24 мая 2011

Нет. Говоря прямо. И в 30 символов.

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

25 голосов
/ 25 мая 2011

Кажется, что использование многомерных массивов проще с массивами 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] будет очень дорогостоящим для копирования.

13 голосов
/ 11 августа 2011

Как сказал Сумант, многомерные массивы намного проще использовать со встроенными 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

5 голосов
/ 23 марта 2014

Массивы в стиле C, доступные в C ++, на самом деле гораздо менее универсальны, чем реальные C-массивы. Разница в том, что в C типы массивов могут иметь размеры runtime . Следующее является допустимым кодом C, но его нельзя выразить ни с помощью массивов в стиле C ++, ни с типами 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, описанный выше, но он должен выполнять вычисление индекса вручную везде, где используются индексы . Для двумерного случая это все еще возможно (даже при том, что у него есть много возможностей ошибиться при расчете индекса). Однако в 3D-случае это становится очень неприятным.

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

0 голосов
/ 22 апреля 2015

Может быть std::array не медленно. Но я провел несколько сравнительных тестов с использованием простого хранения и чтения из массива std :: См. Результаты тестов ниже (на 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

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

Код класса эталона здесь ;

Я мало что знаю о бенчмаркингах ... Мой код может быть ошибочным

0 голосов
/ 24 мая 2011
  1. реализовать что-то вроде std::array
  2. если вы не хотите использовать STL или не можете
  3. Для исполнения
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...