#c #arrays
#c #массивы
Вопрос:
Почему я не могу сделать что-то подобное:
int size = menu.size;
int list[size];
Есть ли что-нибудь вокруг этого вместо использования вектора? (массивы работают быстрее, поэтому я хотел использовать массивы)
Спасибо
Комментарии:
1. (массивы быстрее, поэтому я хотел использовать массивы) — Пожалуйста, расскажите нам, при каких обстоятельствах массивы быстрее и как использование a
vector
может вызвать узкое место в вашем коде. Как новичку, вам действительно следует избегать неверных предположений о производительности вашего кода. В подавляющем большинстве случаев вы никогда не увидите разницы в производительности и избежите различных типов ошибок, связанных с использованием необработанных массивов.2. если вы беспокоитесь о производительности между вектором и массивом, вы лаете не на то дерево. гораздо большие потери производительности в 99,9% случаев зависят от алгоритма или ввода-вывода.
3. Да, эти ребята правы. Раньше я думал так же, как и ты. Я использую, чтобы попытаться реализовать свои собственные динамические массивы, когда я начал c . Теперь я понял, что я в основном делал то же самое, что и вектор, и векторная реализация, вероятно, быстрее и безопаснее, чем моя. Однако это не значит, что вы не должны играть с массивами в куче в учебных целях. Вы получите лучшее представление о том, как все работает, если попробуете сделать это самостоятельно.
Ответ №1:
Размер должен быть известен во время компиляции, поскольку компилятору необходимо знать, сколько места в стеке потребуется, чтобы выделить для него достаточно памяти. (Редактировать: я исправлен. В C массивы переменной длины могут быть размещены в стеке. Однако C не допускает массивов переменной длины.)
Но вы можете создавать массивы в куче во время выполнения:
int* list = new int[size];
Просто убедитесь, что вы освободили память, когда закончите, или вы получите утечку памяти:
delete [] list;
Обратите внимание, что очень легко случайно создать утечки памяти, а вектор почти наверняка проще в использовании и обслуживании. Векторы работают довольно быстро (особенно если сначала вы reserve()
их до нужного размера), и я настоятельно рекомендую использовать вектор вместо ручного управления памятью.
В общем, хорошей идеей будет профилировать ваш код, чтобы выяснить, где находятся реальные узкие места, чем проводить предварительную микрооптимизацию (потому что оптимизация не всегда является оптимизацией).
Комментарии:
1. Опять же, если ваш первый абзац был true, то VLAS не могли существовать в C.
2. Я знаю, что мой список не будет очень большим, но разве хранение чего-либо в куче не происходит медленно, так как для его извлечения им нужно обращаться к памяти? (просто чтобы я знал в будущем). Спасибо
3. @Danny: Что бы вы ни делали, элементы, которые вы хотите сохранить, в конечном итоге окажутся в памяти (будь то стек или куча). Доступ к ним из стека не будет быстрее (за исключением проблем с кэшированием). Куча требует немного больше учета, поэтому получение памяти может быть немного медленнее, но незначительно для большинства приложений. Если объявление памяти в куче становится вашим узким местом, вы можете реализовать какой-то механизм повторного использования массива (или использовать специализированный распределитель)
4. @Cameron Спасибо за информацию 🙂
Ответ №2:
Как уже говорили другие, разработчики языка C решили не разрешать массивы переменной длины, VLA, несмотря на то, что они доступны в C99. Однако, если вы готовы проделать немного больше работы самостоятельно, и вам просто отчаянно нужно выделить память в стеке, вы можете использовать alloca()
.
Тем не менее, я лично использовал std::vector
бы . Это проще, безопаснее, удобнее в обслуживании и, вероятно, достаточно быстро.
Комментарии:
1. 1 alloca() — это ответ, если вы действительно, действительно хотите распределять массивы динамического размера в стеке во время выполнения на C . Но будьте осторожны…. Переполнение стека! ахнуть
2. Или используйте VLAS с расширением компилятора (gcc).
Ответ №3:
C не допускает использования массивов переменной длины. Размер должен быть известен во время компиляции. Так что вы не можете этого сделать.
Вы можете использовать векторы или new
.
vector<int> list;
или
int *list = new int[size];
Если вы выберете последнее, вам нужно будет освободить его позже:
delete[] list;
массивы работают быстрее, поэтому я хотел использовать массивы
Это не так. Откуда вы это услышали?
Ответ №4:
В C длина массива должна быть известна во время компиляции, чтобы разместить его в стеке.
Если вам нужно выделить массив, размер которого вы не знаете во время компиляции, вам нужно будет выделить его в куче, используя operator new[]
int size = menu.size;
int *list = new int[size];
Но поскольку у вас есть новая память в куче, вам необходимо убедиться, что вы правильно удалили ее, когда закончите с ней.
delete[] list;
Комментарии:
1. Смотрите мои комментарии к другим вопросам — ваш первый абзац чрезмерно решителен. Возможно создание систем, в которых размеры выделения стековой памяти могут быть определены во время выполнения.
Ответ №5:
AFAIK В C 03 нет массивов переменной длины (VLA):
вы, вероятно, хотите это сделать:
const int size = menu.size;
int list[size]; // size is compile-time constant
или
int *list = new int[size]; // creates an array at runtime;
delete[] list; // size can be non-const
Ответ №6:
во-первых, векторы не намного быстрее. что касается причины, по которой вы не можете сделать что-то подобное:
код выделит массив в стеке. компиляторы должны заранее знать этот размер, чтобы они могли его учесть. следовательно, вы можете использовать константы только с таким синтаксисом.
самый простой способ — создать массив в куче: int list = new int[size];
не забудьте delete[]
сделать это позже. Однако, если вы используете вектор и заранее резервируете правильный размер компилируете с оптимизацией, накладных расходов должно быть немного или совсем не должно быть.
Комментарии:
1. Одним из интересных аспектов этого в C является то, что если вы пишете
int a[n]
, гдеn
объявлено черезconst
, то вы фактически получаете VLA, т. Е. Выделение стека резервируется во время выполнения, а не во время компиляции. Это потому, что Cconst
означает только для чтения, а не константу.
Ответ №7:
Поскольку list
он размещен в стеке, его размер должен быть известен во время компиляции. Но здесь size
это неизвестно до времени выполнения, поэтому размер list
не известен во время компиляции.
Комментарии:
1. Если бы это было правдой, то ВЛАс не существовал бы в C.
2. В данном случае это верно, потому что это C , а не C.
3. Я хочу сказать, что проблема не в том, что
list
выделено в стеке. Проблема в том, что язык C не поддерживает VLAS. Это возможно, если языковой комитет решит, что они хотят это сделать. Таким образом, ваш ответ не должен говорить о том, что размер известен во время компиляции. Следует просто сказать, что вы не можете сделать это в C .