Статический массив против динамического массива в C ++

В чем разница между статическим массивом и динамическим массивом в C ++?

Я должен выполнить задание для своего класса, и в нем говорится, что нельзя использовать статические массивы, а только динамические массивы. Я искал в книге и в Интернете, но, кажется, не понимаю.

Я думал, что статика была создана во время компиляции, а динамическая - во время выполнения, но я мог ошибиться с выделением памяти.

Можете ли вы объяснить разницу между статическим массивом и динамическим массивом в C ++?


person user69514    schedule 20.04.2010    source источник
comment
Статика не противоположна динамике. Либо книга, которую вы используете, ужасна, либо вы вырываете ее из контекста. Я собираюсь добавить новый ответ ниже, чтобы, надеюсь, прояснить это.   -  person Joshua Clayton    schedule 23.07.2013
comment
См. Диаграмму в этом вопросе: stackoverflow.com/a/11698458/1143274 Статические массивы не размещаются в стеке или куча.   -  person Evgeni Sergeev    schedule 26.12.2013
comment
* фиксированный массив против динамического массива   -  person csguy    schedule 11.09.2019


Ответы (11)


Локальные массивы создаются в стеке и имеют автоматическую продолжительность хранения - вам не нужно вручную управлять памятью, но они уничтожаются, когда функция, в которой они находятся, завершается. У них обязательно есть фиксированный размер:

int foo[10];

Массивы, созданные с помощью operator new[], имеют динамическую продолжительность хранения и хранятся в куче (технически «бесплатное хранилище»). Они могут иметь любой размер, но вам нужно выделить и освободить их самостоятельно, поскольку они не являются частью кадра стека:

int* foo = new int[10];
delete[] foo;
person Michael Mrozek    schedule 20.04.2010
comment
Это правильно, но только для иллюстрации того, как это работает. Пожалуйста, не делайте этого в реальном коде, вместо этого используйте std :: vector. - person Eddy Pronk; 20.04.2010
comment
@Eddy: Это зависит от ситуации, нужен ли вектор - person Casebash; 14.10.2010
comment
@Casebash: в какой ситуации вы бы предпочли массив? Вы всегда должны предпочесть использовать векторы или двухсторонние объекты вместо массивов. - Herb Sutter (более исключительный C ++) - person Eddy Pronk; 15.10.2010
comment
Если вас устраивает установка максимального размера во время создания, тогда вам не нужен вектор. На самом деле случается время от времени. - person Casebash; 15.10.2010
comment
@Casebash: в этом случае использование вектора также не требует дополнительных затрат. - person Eddy Pronk; 15.10.2010
comment
@EddyPronk По причинам фрагментации памяти можно использовать фиксированный массив как своего рода пул. Не в каждом случае требуется куча, есть особые преимущества использования массивов на основе стека. Вы относитесь к std :: vector как к золотому молотку, распространенному антипаттерну. - person void.pointer; 10.10.2011
comment
@EddyPronk: Я почти уверен, что Херб Саттер имел в виду динамические массивы, такие как int* foo = new int[N], которые вы должны delete сами и, следовательно, будьте осторожны при наличии исключения. Статические массивы не имеют этих проблем. - person Alexander Malakhov; 11.02.2013
comment
Лучшие практики предлагают: не забудьте сбросить указатель foo = NULL; после delete[] foo;. Потому что в некоторых системах delete не сбрасывает указатель. - person vulcan raven; 20.05.2013
comment
@vulcanraven Значит, в некоторых системах delete действительно сбрасывает указатель? Я не знал и всегда вызываю foo = NULL после, если только он не выходит за пределы области действия, как в деструкторе (я всегда видел delete как функцию передачи по значению, поэтому не имеет доступа к &foo, а затем не могу установите его на ноль). - person Boris Dalstein; 21.06.2013
comment
Когда я думаю о статическом массиве, я думаю, что static int foo[x] и он не размещен в стеке. - person Z boson; 17.10.2014
comment
Неаккуратная формулировка - ›Статические массивы создаются в стеке. О чем идет речь, когда говорится о статическом массиве? Следует четко указать различия между static int a[5]; и { int a[5]; } (локальная переменная a) и int a[5]; (глобальная переменная a). Таким образом, этот ответ неполон и сбивает с толку. - person P.P; 17.10.2014
comment
Ваше редактирование более точное, но менее точное (в предыдущей версии было наоборот). Вы сейчас даже не используете слово «статика». Вопрос OP заключался в том, можете ли вы объяснить разницу между статическим массивом и динамическим массивом в C ++ ?. - person Z boson; 17.10.2014
comment
@Zboson Что ж, здесь вам нужно выбрать одно или другое. Мне показалось, что вопрос имел в виду это различие массивов, и просто использовал неправильную терминологию. Я использовал ту же терминологию, отвечая на вопрос, чтобы он был понятен, но исправил это сейчас, потому что, по-видимому, 4 года спустя это внезапно стало проблемой. Не стесняйтесь редактировать его, если это сбивает с толку; мне это кажется совершенно ясным - person Michael Mrozek; 17.10.2014
comment
@MichaelMrozek, вы могли бы объяснить, что существуют разные типы статических массивов (например, локальные и глобальные), но в любом случае я либо добавлю свой ответ, либо задам вопрос. - person Z boson; 17.10.2014
comment
std :: array ›std :: vector для относительно небольших массивов статического размера. - person WaelJ; 20.10.2014

static - это ключевое слово в C и C ++, поэтому вместо общего описательного термина static имеет очень конкретное значение при применении к переменной или массиву. Чтобы усугубить путаницу, он имеет три различных значения в разных контекстах. По этой причине статический массив может быть фиксированным или динамическим.

Позволь мне объяснить:

Первый специфичен для C ++:

  • Статический член класса - это значение, которое не создается с помощью конструктора или не удаляется с помощью деструктора. Это означает, что член должен быть инициализирован и поддерживаться другим способом. статический член может быть указателями, инициализированными значением null и затем выделенными при первом вызове конструктора. (Да, это было бы статично и динамично)

Два унаследованы от C:

  • внутри функции статическая переменная - это переменная, место в памяти которой сохраняется между вызовами функций. Он статичен в том смысле, что инициализируется только один раз и сохраняет свое значение между вызовами функций (использование статики делает функцию нереентерабельной, т. Е. Не потокобезопасной)

  • статические переменные, объявленные вне функций, являются глобальными переменными, к которым можно получить доступ только из того же модуля (файл исходного кода с любыми другими # include)

Вопрос (я думаю), который вы хотели задать, заключается в том, в чем разница между динамическими массивами и фиксированными массивами или массивами времени компиляции. Это более простой вопрос, массивы времени компиляции определяются заранее (при компиляции программы) и являются частью фрейма стека функций. Они выделяются до запуска основной функции. динамические массивы выделяются во время выполнения с помощью ключевого слова "new" (или семейства malloc из C), и их размер заранее не известен. динамические выделения не очищаются автоматически, пока программа не остановится.

person Joshua Clayton    schedule 23.07.2013
comment
+1, ваш ответ самый точный и точный и должен был получить больше голосов. - person Z boson; 17.10.2014
comment
Если вы объявляете размер массива с помощью оператора new[], как получается, что размер неизвестен до времени выполнения? т.е. int* p = new int[10] - person wulfgarpro; 22.06.2016
comment
Они выделяются до запуска основной функции. Зачем выделять переменные стека до того, как будет введен соответствующий блок? - person AlwaysLearning; 18.09.2019
comment
Переменные стека (обычно локальные переменные в функции) имеют предопределенный размер и положение в кадре стека, и весь стек выделяется до запуска основной функции, @AlwaysLearning. При вводе фрейма стека через вызов функции указатель стека обновляется, но новый фрейм стека находится внутри стека. Больше стека не выделяется. Фактически, слишком большое количество переменных (например, гигантский массив) или слишком много одновременных вызовов функций приводит к переполнению стека, в честь которого назван этот сайт. - person Joshua Clayton; 22.09.2019
comment
@JoshuaClayton Я думаю, это не может быть правильно. Как вы можете выделить кадры стека (обратите внимание на множественное число) для рекурсивной функции, если вы не знаете, сколько раз она будет вводиться? - person AlwaysLearning; 22.09.2019
comment
Кадры стека не выделяются индивидуально (т.е. память для них не запрашивается у ОС). Они добавляются в стек, который уже был выделен при создании экземпляра процесса. - person Joshua Clayton; 24.09.2019
comment
Правильно ли вообще называть фиксированные массивы, статические массивы? - person csguy; 19.11.2019
comment
@csguy static - это ключевое слово, которое означает исправление определенными способами, описанными выше. const также означает исправлено другим способом. Что вы имеете в виду под фиксированным? - person Joshua Clayton; 19.11.2019
comment
@JoshuaClayton, о, я думал, вы сказали в своем ответе, что статический массив означает фиксированный массив, а не динамический массив, но вы говорите, что статические массивы могут быть динамическими или фиксированными / правильными по времени компиляции? - person csguy; 20.11.2019

Я думаю, что семантика, используемая в вашем классе, сбивает с толку. Под «статическим», вероятно, подразумевается просто «постоянный размер», а под «динамическим», вероятно, подразумевается «переменный размер». В этом случае массив постоянного размера может выглядеть так:

int x[10];

а «динамическая» - это просто структура любого вида, которая позволяет увеличивать или уменьшать базовое хранилище во время выполнения. В большинстве случаев достаточно класса std::vector из стандартной библиотеки C ++. Используйте это так:

std::vector<int> x(10); // this starts with 10 elements, but the vector can be resized.

std::vector определен operator[], поэтому вы можете использовать его с той же семантикой, что и массив.

person Ben Collins    schedule 20.04.2010
comment
Я думаю, довольно ясно, что под динамическим массивом они просто подразумевают динамически распределенный массив (то есть тот, в котором размер может быть определен динамически во время выполнения). Нравится new int[10] - person jalf; 20.04.2010
comment
@jalf: Меня больше беспокоил термин «статика». Я предпочитаю называть динамический массив массивом выделенного или переменного размера для согласованности. - person Ben Collins; 23.04.2010
comment
Хороший момент, потому что статический массив может быть автоматическим и реализован в стеке или быть глобальным и реализован в разделе данных. Оба являются статическими, но внутренне код, который обращается к ним, может сильно отличаться. - person Z boson; 17.10.2014

Важно иметь четкие определения того, что означают термины. К сожалению, существует несколько определений того, что означают статические и динамические массивы.

Статические переменные - это переменные, определенные с помощью статическое распределение памяти. Это общая концепция, не зависящая от C / C ++. В C / C ++ мы можем создавать статические переменные с глобальной, файловой или локальной областью видимости следующим образом:

int x[10]; //static array with global scope
static int y[10]; //static array with file scope
foo() {
    static int z[10]; //static array with local scope

Автоматические переменные обычно реализуются с использованием распределение памяти на основе стека. Автоматический массив можно создать на C / C ++ следующим образом:

foo() {
    int w[10]; //automatic array

Общим для этих массивов x, y, z и w является то, что размер каждого из них фиксирован и определяется во время компиляции.

Одна из причин, по которой важно понимать различие между автоматическим массивом и статическим массивом, заключается в том, что статическое хранилище обычно реализуется в раздел данных (или раздел BSS) объекта файл, и компилятор может использовать абсолютные адреса для доступа к массивам, что невозможно при хранении на основе стека.

Под динамическим массивом обычно подразумевается не тот, размер которого можно изменять, а тот, который реализован с использованием динамическое выделение памяти с фиксированным размером, определяемым во время выполнения. В C ++ это делается с помощью оператора new.

foo() {
   int *d = new int[n]; //dynamically allocated array with size n     

Но можно создать автоматический массив с размером исправлений, определенным во время выполнения, используя alloca:

foo() {
    int *s = (int*)alloca(n*sizeof(int))

Для настоящего динамического массива следует использовать что-то вроде std::vector в C ++ (или массив переменной длины в C ).

Что означало задание в вопросе ОП? Я думаю, ясно, что то, что требовалось, было не статическим или автоматическим массивом, а тем, в котором либо использовалось динамическое распределение памяти с помощью оператора new, либо массив нефиксированного размера, например, std::vector.

person Z boson    schedule 20.10.2014

Статическим массивам выделяется память во время компиляции, а память выделяется в стеке. В то время как динамическим массивам выделяется память во время выполнения, а память выделяется из кучи.

int arr[] = { 1, 3, 4 }; // static integer array.   
int* arr = new int[3]; // dynamic integer array.
person Jagannath    schedule 20.04.2010
comment
Глобальный массив - это статический массив, который реализован в разделе данных, а не из стека. - person Z boson; 17.10.2014

Я думаю, в этом контексте это означает, что он статичен в том смысле, что размер фиксирован. Используйте std :: vector. Он имеет функцию resize ().

person Eddy Pronk    schedule 20.04.2010

У вас может быть псевдодинамический массив, размер которого устанавливается пользователем во время выполнения, но затем фиксируется после этого.

int size;
cin >> size;
int dynamicArray[size];
person Joshua Oliphant    schedule 17.10.2014
comment
Не является частью стандартного C ++ (в C99 и как расширение компилятора для gcc). - person crashmstr; 20.10.2014

Статический массив:

  1. Статическим массивам выделяется память во время компиляции.
  2. Размер фиксированный.
  3. Находится в стековой памяти.
  4. Например. : int array [10]; // массив размером 10

Динамический массив:

  1. Память выделяется во время выполнения.
  2. Размер не фиксирован.
  3. Находится в области памяти кучи.
  4. Например. : int * array = new int [10];
person Tejashree Kudale    schedule 15.09.2020

Да, верно, статический массив создается во время компиляции, а динамический массив создается во время выполнения. Хотя разница в том, что касается их ячеек памяти, статические находятся в стеке, а динамические создаются в куче. Все, что находится в куче, требует управления памятью до тех пор, пока не будет установлен сборщик мусора, как в случае .net framework, в противном случае существует риск утечки памяти.

person Aadil Imran    schedule 27.02.2013

Статический массив: Эффективность. Никакого динамического выделения или освобождения не требуется.

Массивы, объявленные в C, C ++ в функции, включая модификатор static, являются статическими. Пример: static int foo [5];

person Khuê Phạm    schedule 17.12.2013
comment
@admdrew, это правда, но на этот вопрос так и не ответили должным образом. Лучший ответ - ответ Джошуа Клейтона, но я думаю, что лучший ответ - это заголовок stackoverflow.com/questions/17775066/ - person Z boson; 17.10.2014
comment
@Zboson Полезно знать, спасибо. Хе и я только что поняли, что я сделал этот комментарий почти год назад. - person admdrew; 17.10.2014

статические произвольные меры с подачей элементов в сторону массива

динамический произвольный вид без дополнительных элементов в массиве

пример:

     char a[10]; //static array
       char a[];  //dynamic array
person karthik    schedule 27.02.2013
comment
Думаю, он сказал правильно. Когда вы задаете точную длину для массива, это статический массив, а когда вы не указываете длину, это динамический массив. но поскольку он не знает, как писать по-английски, люди отмечают этот ответ. - person muhammad tayyab; 10.01.2015