Поскольку std::listи std::vectorсуществует, есть ли причина использовать традиционные массивы C в C ++ или их следует избегать, как и malloc?
Поскольку std::listи std::vectorсуществует, есть ли причина использовать традиционные массивы C в C ++ или их следует избегать, как и malloc?
Ответы:
В C ++ 11, где std::arrayэто возможно, ответ - «да, следует избегать массивов». До C ++ 11 вам может потребоваться использовать массивы C для размещения массивов в автоматическом хранилище (то есть в стеке).
Определенно, хотя и std::arrayв C ++ 11, практически только для статических данных. Массивы в стиле C имеют три важных преимущества перед
std::vector:
Им не требуется динамическое размещение. По этой причине массивы в стиле C предпочтительнее там, где у вас, вероятно, будет много очень маленьких массивов. Скажите что-нибудь вроде точки n размерности:
template <typename T, int dims>
class Point
{
T myData[dims];
// ...
};
Как правило, можно представить себе dimsочень маленький (2 или 3)
Tвстроенный тип ( double), который в итоге может получить
std::vector<Point>миллионы элементов. Вам определенно не нужны миллионы динамических распределений 3 double.
Поддержка статической инициализации. Это проблема только для статических данных, например:
struct Data { int i; char const* s; };
Data const ourData[] =
{
{ 1, "one" },
{ 2, "two" },
// ...
};
Это часто предпочтительнее использования вектора (и std::string), так как это позволяет избежать всех проблем с порядком инициализации; данные предварительно загружаются до того, как можно будет выполнить какой-либо фактический код.
Наконец, в связи с вышеизложенным, компилятор может вычислить фактический размер массива из инициализаторов. Их не нужно считать.
Если у вас есть доступ к C ++ 11, он std::arrayрешает первые две проблемы и, безусловно, должен использоваться вместо массивов стиля C в первом случае. Однако он не обращается к третьему, и наличие размерности массива в соответствии с количеством инициализаторов компилятором по-прежнему является веской причиной для предпочтения массивов в стиле C.
int i[] = { 1, 2, 3 };продолжает работать с int i[] = { 1, 2, 3, 4 };. array<int, 3>необходимо вручную изменить на array<int, 4>.
make_arrayфункцию , аналогичную и make_pairт. Д. Подсказка к @R. Мартиньо Фернандес .
std::arrayв C ++ 11 [их следует использовать] практически только для статических данных».
Никогда не говорите «никогда», но я согласен с тем, что их роль значительно уменьшается из-за настоящих структур данных из STL.
Я бы также сказал, что инкапсуляция внутри объектов должна минимизировать влияние подобного выбора. Если массив является частным членом данных, вы можете поменять местами его, не затрагивая клиентов вашего класса.
Я работал с критически важными для безопасности системами, в которых нельзя использовать динамическое распределение памяти. Память всегда должна быть в стеке. Поэтому в этом случае вы должны использовать массивы, так как размер фиксируется во время компиляции.
std::array<T>выделяет в стеках и в основном не имеет накладных расходов на необработанный массив.
arrayin c++дает вам фиксированный размер быстрой альтернативы динамического размера std::vectorи std::list. std :: array - одно из дополнений в c++11. Он обеспечивает преимущества контейнеров std, в то же время обеспечивая семантику агрегированного типа массивов в стиле C.
Поэтому c++11я бы обязательно использовал там std::array, где это требуется, over vector. Но я бы избежать массив стилей C в C++03.
Чаще всего нет , я не могу придумать причины использовать необработанные массивы, скажем, вместо vectors. Если код новый .
Возможно, вам придется прибегнуть к использованию массивов, если ваши библиотеки должны быть совместимы с кодом, который ожидает массивы и необработанные указатели.
vector.data()в C ++ 11 или &vector.front()ранее.
Я знаю, что многие люди указывают на std :: array для выделения массивов в стеке и std :: vector для кучи. Но ни один из них, похоже, не поддерживает неродное выравнивание. Если вы используете какой-либо числовой код, в котором хотите использовать инструкции SSE или VPX (что требует 128 или 256 байтов выравнивания соответственно), массивы C по-прежнему будут вашим лучшим выбором.
Я бы сказал, что массивы по-прежнему полезны, если вы храните небольшой статический объем данных, почему бы и нет.
Единственное преимущество массива (конечно, обернутого во что-то, что будет автоматически управлять его освобождением при необходимости) над, о котором std::vectorя могу думать, заключается в том, что он vectorне может передать право собственности на свои данные, если ваш компилятор не поддерживает C ++ 11 и конструкторы перемещения.
swap.
Массивы в стиле C - это фундаментальная структура данных, поэтому будут случаи, когда ее лучше использовать. Однако в общем случае используйте более сложные структуры данных, которые скругляют углы базовых данных. C ++ позволяет делать с памятью очень интересные и полезные вещи, многие из которых работают с простыми массивами.
std::arrays? Оба во многих случаях будут скомпилированы в одну и ту же сборку.
std::arrayимеет точно определенную семантику, построенную на основе статических массивов.
Вы должны использовать контейнеры STL внутри, но вы не должны передавать указатели на такие контейнеры между различными модулями, иначе вы попадете в ад зависимостей. Пример:
std::string foo;
// fill foo with stuff
myExternalOutputProc(foo.c_str());
это очень хорошее решение, но не
std::string foo;
// fill foo with stuff
myExternalOutputProc(&foo);
Причина в том, что std :: string можно реализовать разными способами, но строка в стиле c всегда является строкой в стиле c.