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


91

У чому різниця між статичним масивом та динамічним масивом у C ++?

Я повинен зробити завдання для свого класу, і там сказано не використовувати статичні масиви, лише динамічні масиви. Я переглядав книгу та Інтернет, але, схоже, не розумію.

Я думав, що static був створений під час компіляції, а динамічний під час виконання, але, можливо, я помиляюся з виділенням пам'яті.

Чи можете ви пояснити різницю між статичним масивом та динамічним масивом у C ++?


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: У якій ситуації ти віддав би перевагу масиву? "Ви завжди повинні віддавати перевагу використанню векторів або декалів замість масивів." - Herb Sutter (більш винятковий C ++)
Eddy Pronk

16
@EddyPronk З міркувань фрагментації пам'яті можна використовувати фіксований масив як свого роду пул. Не кожен випадок вимагає купи, є особливі переваги використання масивів на основі стеків. Ви поводитесь зі std :: vector як із золотим молотком, загальним антивізером.
void.pointer

4
@EddyPronk: Я майже впевнений, що Herb Sutter мав на увазі динамічні масиви, подібні до int* foo = new int[N]яких ви маєте deleteсобі, а отже, будьте обережні в присутності винятку. Статичні масиви не мають цих проблем.
Олександр Малахов

31

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

Дозволь пояснити:

Перший - специфічний для C ++:

  • Статичний член класу - це значення, яке не створюється за допомогою конструктора або видаляється за допомогою деструктора. Це означає, що член повинен бути ініціалізований і підтримуватися іншим способом. статичним членом можуть бути покажчики, ініціалізовані нулем, а потім виділені при першому виклику конструктора. (Так, це буде статично та динамічно)

Два успадковуються від C:

  • всередині функції, статичною змінною вважається така змінна, пам'ять якої зберігається між викликами функції. Він статичний тим, що він ініціалізується лише один раз і зберігає своє значення між викликами функцій (використання статики робить функцію неповерненою, тобто не безпечною для потоків)

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

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


4
+1, ваша відповідь є найбільш точною та точною, і вона мала набрати більше голосів.
Z бозон

Якщо ви оголосите розмір масиву за допомогою new[]оператора, як це сталося, що розмір невідомий до часу виконання? тобтоint* p = new int[10]
wulfgarpro

"Вони виділяються до запуску основної функції." Навіщо виділяти змінні стека до введення відповідного блоку?
Завжди Навчання

Змінні стека (як правило, локальні змінні у функції) мають заздалегідь визначений розмір і положення в кадрі стека, і весь стек виділяється до запуску основної функції @AlwaysLearning. Під час введення кадру стека за допомогою виклику функції вказівник стека оновлюється, але новий кадр стека знаходиться всередині стека. Більше стека ніколи не виділяється. Насправді, занадто велика кількість змінних (наприклад, гігантський масив) або занадто багато відкритих викликів функцій призводять до переповнення стека, якому і названо цей сайт.
Джошуа Клейтон,

@JoshuaClayton Я думаю, це не може бути правильно. Як можна розподілити рамки стека (зверніть увагу на множину) для рекурсивної функції, коли ви не знаєте, скільки разів вона буде введена?
Завжди Навчання

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
Я думаю, цілком зрозуміло, що під "динамічним масивом" вони просто мають на увазі динамічно виділений масив (тобто такий, у якому розмір можна динамічно вказувати під час виконання). Подобаєтьсяnew 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 ).

Що було призначено для доручення у питанні OP? Я думаю, зрозуміло, що хотілося не статичного або автоматичного масиву, а такого, що використовував динамічний розподіл пам’яті за допомогою newоператора або масив нефіксованого розміру, використовуючи, наприклад std::vector.


3

Я думаю, що в цьому контексті це означає, що він є статичним у тому сенсі, що розмір є фіксованим. Використовуйте std :: vector. Він має функцію resize ().


2

Ви можете мати псевдодинамічний масив, де розмір встановлюється користувачем під час виконання, але потім фіксується після цього.

int size;
cin >> size;
int dynamicArray[size];

Не є частиною стандартного C ++ (у C99 та як розширення компілятора для gcc).
crashmstr

1

Статичний масив :

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

Динамічний масив:

  1. Пам'ять виділяється під час виконання.
  2. Розмір не фіксований.
  3. Розташований у просторі пам'яті Heap.
  4. Напр. : int * array = new int [10];

0

Так, статичний масив створюється під час компіляції, коли динамічний масив створюється під час виконання. Якщо різниця, що стосується їх розташування в пам'яті, статична розташована в стеку, а динамічна - у купі. Все, що знаходиться в купі, потребує управління пам’яттю до тих пір, поки не буде присутній збирач сміття, як у випадку з .net framework, інакше існує ризик витоку пам'яті.


0

Статичний масив: Ефективність. Не потрібно динамічного розподілу чи звільнення.

Масиви, оголошені в C, C ++ у функції, включаючи статичний модифікатор, є статичними. Приклад: static int foo [5];


1
@admdrew, це правда, але на запитання так і не було відповідей. Найкраща відповідь - це відповідь Джошуа Клейтона, але я думаю, що кращою є така
Z boson

@Zboson Приємно знати, дякую. Ми з Хе тільки що зрозуміли, що зробили цей коментар майже рік тому.
admdrew

-3

статичні довільні елементи з подачею на елементи в бічній частині масиву

динамічні довільні елементи без подання елементів у бічній частині масиву

приклад:

     char a[10]; //static array
       char a[];  //dynamic array

Думаю, він сказав правильно. Коли ви маєте точну довжину масиву, це статичний масив, а коли ви не надаєте довжину, це динамічний масив. але оскільки він не знає, як писати англійською, тому люди відзначають цю відповідь.
Мухаммед Тайяб
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.