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

91

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

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

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

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

user69514
источник
1
Статика не противоположна динамике. Либо книга, которую вы используете, ужасна, либо вы вырываете ее из контекста. Я собираюсь добавить новый ответ ниже, чтобы, надеюсь, прояснить это.
Джошуа Клейтон
3
См. Схему в этом вопросе: stackoverflow.com/a/11698458/1143274 Статические массивы не размещаются в стеке или куче.
Евгений Сергеев
* фиксированный массив против динамического массива
csguy

Ответы:

102

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

int foo[10];

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

int* foo = new int[10];
delete[] foo;
Майкл Мрозек
источник
18
Это правильно, но только для иллюстрации того, как это работает. Пожалуйста, не делайте этого в реальном коде, а используйте вместо него std :: vector.
Эдди Пронк
23
@Eddy: Это зависит от ситуации, нужен ли вектор
Casebash
6
@Casebash: в какой ситуации вы бы предпочли массив? «Вы всегда должны предпочесть использовать векторы или двухсторонние объекты вместо массивов». - Херб Саттер (более исключительный C ++)
Эдди Пронк
16
@EddyPronk По причинам фрагментации памяти можно использовать фиксированный массив как своего рода пул. Не в каждом случае требуется куча, есть особые преимущества использования массивов на основе стека. Вы относитесь к std :: vector как к золотому молотку, распространенному антипаттерну.
void.pointer
4
@EddyPronk: Я почти уверен, что Херб Саттер имел в виду динамические массивы, такие как те, int* foo = new int[N]которые есть у deleteвас, и поэтому будьте осторожны при наличии исключения. Статические массивы не имеют этих проблем.
Александр Малахов
31

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

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

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

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

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

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

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

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

Джошуа Клейтон
источник
4
+1, ваш ответ самый точный и точный и должен был получить больше голосов.
Z-бозон
Если вы объявляете размер массива с помощью new[]оператора, как получается, что размер неизвестен до времени выполнения? ieint* p = new int[10]
wulfgarpro
«Они выделяются до запуска основной функции». Зачем выделять переменные стека до того, как будет введен соответствующий блок?
AlwaysLearning
Переменные стека (обычно локальные переменные в функции) имеют предопределенный размер и положение внутри кадра стека, и весь стек выделяется до запуска основной функции, @AlwaysLearning. При вводе фрейма стека через вызов функции указатель стека обновляется, но новый фрейм стека находится внутри стека. Больше стека не выделяется. Фактически, слишком большое количество переменных (например, гигантский массив) или слишком много одновременных вызовов функций приводит к переполнению стека, в честь которого назван этот сайт.
Джошуа Клейтон
@JoshuaClayton Я думаю, это не может быть правильно. Как вы можете выделить кадры стека (обратите внимание на множественное число) для рекурсивной функции, если вы не знаете, сколько раз она будет введена?
AlwaysLearning
11

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

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[]значение, так что вы можете использовать его с той же семантикой , как массив.

Бен Коллинз
источник
1
Я думаю, довольно ясно, что под «динамическим массивом» они просто подразумевают динамически распределенный массив (то есть такой, размер которого может быть определен динамически во время выполнения). Likenew int[10]
jalf
@jalf: Меня больше беспокоил термин «статический». Я предпочитаю называть «динамический массив» выделенным массивом или массивом переменного размера для согласованности.
Бен Коллинз
Хороший момент, потому что статический массив может быть автоматическим и реализован в стеке или быть глобальным и реализован в разделе данных. Оба они статичны, но внутренне код, который обращается к ним, может сильно отличаться.
Z-бозон
9

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

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

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

Статические переменные - это переменные, определенные с использованием статического распределения памяти . Это общая концепция, не зависящая от 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::vectorC ++ (или массив переменной длины в C ).

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

Z-бозон
источник
3

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

Эдди Пронк
источник
2

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

int size;
cin >> size;
int dynamicArray[size];
Джошуа Олифант
источник
Не является частью стандартного C ++ (в C99 и как расширение компилятора для gcc).
crashmstr
1

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

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

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

  1. Память выделяется во время выполнения.
  2. Размер не фиксирован.
  3. Расположен в области памяти кучи.
  4. Например. : int * array = new int [10];
Теджашри Кудале
источник
0

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

Адил Имран
источник
0

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

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

Khuê Phm
источник
1
@admdrew, это правда, но на этот вопрос так и не ответили хорошо. Лучший ответ - ответ Джошуа Клейтона, но я думаю, что лучший ответ - это один stackoverflow.com/questions/17775066/…
Z-бозон
@Zboson Полезно знать, спасибо. Хе и я только что поняли, что я сделал этот комментарий почти год назад.
Admdrew
-3

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

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

пример:

     char a[10]; //static array
       char a[];  //dynamic array
Картик
источник
Думаю, он сказал правильно. Когда вы задаете точную длину для массива, это статический массив, а когда вы не указываете длину, это динамический массив. но поскольку он не знает, как писать по-английски, люди отмечают этот ответ.
мухаммад тайяб