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


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

7 85

7 ответов:

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

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

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

массивы C-стиля, доступные в C++, на самом деле гораздо менее универсальны, чем реальные c-массивы. Разница в том, что в C типы массивов могут иметь runtime размеров. Ниже приведен допустимый код C, но он не может быть выражен ни с помощью массивов C++ C-style, ни с помощью 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-style массивов в 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 (ссылке)

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

Я не знаю много о benchmarkings... Мой код может быть испорчен

  1. реализовать что-то вроде std::array
  2. Если вы не хотите использовать STL или не можете
  3. для исполнения