Какво представляват динамичните C ++ масиви?

Да започнем с това, което е динамичен масив. От времето на Si има масиви, но тяхната характеристика е фиксираният размер, който е отбелязан при създаването и вече не се променя. Поради това те получават името статични масиви. Очевидно е, че динамичният масив означава, че може да промени размера си по време на програмата. Също така може да се създаде, когато броят на предвидените елементи е дори неизвестен, той е празен.

Управление на динамичната памет

Има такова понятие като динамично управление на паметта. Този подход в програмирането ви позволява да извлечете максимума от паметта на компютъра. В C ++ този процес се контролира от новите и операциите за изтриване. Операция new запазва паметта в областта на динамичната памет или така наречената купчина (free store или heap на английски език). Съответно операцията за изтриване освобождава резервацията.


Съгласно стандартите за програмиране за динамична памет е необходимо да се следи и навременното почистване, така че новите и операциите по изтриване често се използват по двойки. Този принцип отдавна е остарял. Неговите корени се увеличават от времето, когато операционните системи бяха лошо наблюдавани за паметта или просто не знаеха как да я почистят сами. Сега операционната система винаги изчиства паметта след изпълнението на програмата. Въпреки това, изричното изчистване на паметта е знак за добър тон в програмирането. Новата операция запазва паметта за обект от определен тип и връща адреса в тази памет. Ако разпределението на паметта по каквато и да е причина не може да бъде изпълнено, тогава операцията ще върне нулев указател (показалец, който не е.)се отнася за нищо) и хвърля изключение. Новият оператор работи с обекти от всякакъв тип данни: double, char, int и др. Разпределението на паметта и нейното премахване са както следва.




int * p = new int; //* - означава, че променливата е показалец. Указателите съхраняват адреси.
* р = 9;
изтриване p;

Едномерен масив

Създаването на едномерна динамична решетка е същото като създаването на променлива в куп.

двойно * а = ново двойно 
; //a - показалец към паметта, разпределена на масив от 10 елемента от тип double
a
= 2.5; 22) заличава се [] a; //погледнете отблизо този дизайн! Тя е хитър!

След изявлението за изтриване е необходимо да се посочат квадратни скоби, които да маркират бъдещата операция за програмата като освобождаване не само на показалеца към масива, но и на самия масив.

Двуизмерен масив

Създаването на едномерен динамичен масив е тривиална задача. И ако имаме нужда от многомерен масив

двойно ** ma = ново двойно * 
; //стъпка 1
за (int I = 0; I ma [i] = ново двойно
;

По този начин, създаването на динамичен масив в C ++ размер 5 10. Буквално това означава в първата стъпка да се разпредели в паметта масив от 5 елемента, а след това, във втората стъпка, да се разпредели памет към масив от 10 елемента и да се напише адреса в него в предишния масив, и така за всяка колона. 31]

Защо да използваме указател от втори ред? Това е указател към показалеца. Малко е трудно да се разбере. Въпреки че кодът буквално ни казва да стигнем до някаква стойност, запаметена в масив, трябва да отидем на адреса, да получимима друг адрес и след това излизаме на стойност.


& lt; script type = "text /javascript" & gt;
може да blockSettings2 = {blockId: "R-A-70350-2", renderTo: "yandex_rtb_R-A-70350-2", async:! 0};

if (document.cookie.indexOf ("abmatch =") & gt; = 0) {
blockSettings2 = {blockId: "RA-70350-2", renderTo: "yandex_rtb_R-A-70350- 2 ", statId: 70350async:! 0};
}

Функция (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (функция () {Ya .Context.AdvManager.render (blockSettings2)}), e = b.getElementsByTagName ("скрипт") , d = b.createElement ("script"), d.type = "text /javascript", d.src = "//an.yandex.ru/system/context.js", d.async =! 0e.parentNode.insertBefore (d, e)} (това, този.документ, "yandexContextAsyncCallbacks");

Не забравяйте, че дизайнът на освобождаването на памет за масив трябваше да бъде запомнен? Двуизмерният масив се унищожава по следния начин.

за (int I = 0; i delete [] ma [i];
//изглежда, че сме забравили нещо
delete [] ma;

Къде е "говорителят"?

В началото се казваше, че размерът на динамичния масив се променя, докато програмата работи, но в примерите по-горе Тази промяна не е изрично посочена навсякъде.Размерите на промяната на масива се правят по следния алгоритъм:

  1. В паметта се създава нов масив от необходими размери.
  2. Данните на стария масив се пренаписват в нов масив.
  3. Старият масив е унищожен.

STL вектор - нов динамичен масив

За да използвате вектори, трябва да свържете.

Както знаете, стандартната библиотека с шаблони (STL) е снабдена с набор от контейнери, които управляват колекциите от елементи. Контейнерите са последователни контейнери. Те се различават главно в подредеността на елементите в момента на вмъкване. С други думи, първият елемент винаги ще бъде първият, вторият винагиВторият и т.н. Съществуват и други видове контейнери - асоциативни, подредени по стойност на елементите и нерегулирани изцяло.

Един такъв последователен контейнер е вектор. Той управлява елементи от масива C ++ в динамичната памет. Достъпът до тези елементи се извършва директно от индекса. Поради факта, че векторът е последователен контейнер, добавянето и отстраняването на елементи се извършва в края на масива и тези операции се извършват много бързо. Вмъкването на нов елемент в средата или началото на вектора обаче става много по-бавно, тъй като за тази процедура ще трябва да премести всички предишни елементи към текущия номер на вмъкване. Помислете за пример.

# включва
# включва
int main () {
std :: vector v ; //създаваме празен вектор за съхраняване на елементи от тип int
//дефинирането на вектор е std пространствен шаблон, така std ::
за (int i = 0; i v.push_back (i);
}
за (int i = 0; i std :: cout v [i] ";";
}
std :: cout std :: endl;
система ("пауза");
}

Както можете да видите от кода, работата с вектори се извършва по същия начин като с масивите, докато векторите са снабдени с полезни допълнителни свойства, като C ++ функцията за динамични масиви. Строго погледнато, тези членни функции принадлежат на контейнера.


& lt; script type = "text /javascript" & gt;
може да blockSettings3 = {blockId: " RA-70350-3 ", отдаване под наем erTo: "yandex_rtb_R-A-70350-3", async: 0};

, ако (document.cookie.indexOf ("abmatch =") & gt; = 0) {
blockSettings3 = {blockId : "RA-70350-3", renderTo: "yandex_rtb_R-A-70350-3", statId: 70350async:! 0};
}

! функция (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (функция () {Ya.Context.AdvManager.render (blockSettings3)} , e = b.getElementsByTagName ("скрипт") , d = b.createElement ("скрипт"), d.type = "text /javascript", d.src = "//an.yandex.ru/system /context.js ", d.async =! 0e.parentNode.insertBefore (d, e)} (това, този документ," yandexContextAsyncCallbacks ");

Достъп до векторни елементи

Получаването на достъп до векторни елементи е тема, която трябва да се обсъди отделно. Има следните начини да се отнасят до елементите на вектора.

V [index]

Стандартно позоваване по индекс

V. at (индекс)

Обжалване на елемент с индекс, но изключенията се генерират при излизане от обхвата

V. front ()

Обжалване на първия елемент на вектора

V. обратно ()

Обжалване на последния елемент на вектора

Очевидно най-правилният начин за достъп до векторния елемент е да се извика функцията .at (), тъй като тя генерира изключение out_of_range, което може да бъде обработено в блока try-catch. Функцията [] и функцията .front () .back () работят по непредсказуем начин, когато са извън допустимия диапазон.

Двуизмерен вектор

Да разгледаме пример за създаване на двуизмерен динамичен масив C ++ - проста матрица 5 от 5.



вектор & gt; v (5 вектор 
);
v
= 10;
int a = v
;
v
.push_back
; //създаваме нов елемент в края на вектора
v
.pop_back (); //изтрива последния елемент

Свързани публикации