Поскольку 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>
выделяет в стеках и в основном не имеет накладных расходов на необработанный массив.
array
in 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::array
s? Оба во многих случаях будут скомпилированы в одну и ту же сборку.
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.