Ãëàâà 5: Ñâîáîäíà ïàìåò è ïðåçàðåäèìè èìåíà
Ñúäúðæàíèå íà ïåòà
ãëàâà :
5.1. Ðàçïðåäåëåíèå íà ñâîáîäíàòà ïàìåò
5.2. Åäèí ïðèìåð çà
ñâúðçàí ñïèñúê
5.3. Ïðåçàðåäèìè èìåíà íà ôóíêöèè
5.4. Óêàçàòåëè êúì
ôóíêöèè
5.5. Ñâúðçâàíå, áåçîïàñíî îòíîñíî òèïîâåòå
Òàçè ãëàâà
ðàçãëåæäà äâå ôóíäàìåíòàëíè êîíöåïöèè - ñâîáîäíàòà ïàìåò çà ïðîãðàìàòà è
ïðåçàðåæäàíåòî íà èìåíàòà íà ôóíêöèèòå. Ñâîáîäíàòà çà ïðîãðàìàòà ïàìåò ïîçâîëÿâà
äà ñå îòäåëÿ ïàìåò ïî âðåìå íà èçïúëíåíèå. Ðåàëèçàöèÿòà íà êëàñà IntArray â
ãëàâà 1 íè ïðåäëîæè åäèí êðàòúê ïúðâè ïîãëåä âúðõó òîçè ïðîáëåì. Â òàçè ãëàâà
íèå ùå ãî ðàçãëåäàìå ïîäðîáíî. Ïðåçàðåæäàíåòî íà èìåíàòà íà ôóíêöèèòå ïîçâîëÿâà
íà íÿêîëêî åêçåìïëÿðà íà äàäåíà ôóíêöèÿ, êîÿòî ïðåäëàãà åäíà îáùà îïåðàöèÿ,
îòíàñÿùà ñå çà àðãóìåíòè îò ðàçëè÷åí òèï, äà èìàò åäíî è ñúùî èìå. Àêî âå÷å ñòå
íàïèñàëè ïîíå åäèí àðèòìåòè÷åí èçðàç íà íÿêîé ïðîãðàìåí åçèê, òî âèå ñòå
èçïîëçâàëè ïðåäâàðèòåëíî äåôèíèðàíè ïðåçàðåäèìè ôóíêöèè. Â òàçè ãëàâà íèå ùå
âèäèì êàê äà äåôèíèðàìå íàøè ñîáñòâåíè òàêèâà ôóíêöèè.
5.1.
Ðàçïðåäåëåíèå íà ñâîáîäíàòà ïàìåò
Âñÿêà ïðîãðàìà ðàçïîëàãà ñ èçâåñòíî
êîëè÷åñòâî íåðàçïðåäåëåíà ñâîáîäíà ïàìåò, êîÿòî ìîæå äà èçïîëçâàò ïî âðåìå íà
èçïúëíåíèåòî ñè. Òàçè íàëè÷íà ïàìåò ñå íàðè÷à ñâîáîäíà ïàìåò íà ïðîãðàìàòà è
÷ðåç èçïîëçâàíåòî íà êëàñúò IntArray ìîæå äà îòëîæè ðàçïîëàãàíåòî íà ñâîèòå
ïðåäñòàâèòåëè ìàñèâè â ïàìåòòà çà ïåðèîäà íà èçïúëíåíèåòî. Íåêà ïîãëåäíåì êàê
áåøå íàïðàâåíî òîâà
IntArray
IntArray( int sz ) {
size = sz;
ia
= new int[ size ];
for ( int i = 0; i < sz; ++i ) ia[ i ] =
0;
}
IntArray èìà äàííîâè åëåìåíòà size è ia. ia, êîéòî å óêàçàòåë êúì
öÿëî ÷èñëî, ùå àäðåñèðà ðàçïîëîæåíèåòî íà ìàñèâà â ñâîáîäíàòà ïàìåò. Åäèí îò
àñïåêòèòå íà èçïîëçâàíåòî íà ñâîáîäíàòà ïàìåò å, ÷å òÿ íå å èìåíóâàíà. Îáåêòèòå,
ðàçïîëîæåíè â òàçè ïàìåò, ñå îáðàáîòâàò èíäèðåêòíî ÷ðåç óêàçàòåëè. Âòîðè àñïåêò
íà èçïîëçâàíåòî íà ñâîáîäíàòà ïàìåò, å, ÷å òÿ íå å èíèöèàëèçèðàíà è ñëåäîâàòåëíî
âèíàãè òðÿáâà äà é áúäå äàâàíà ñòîéíîñò ïðåäè óïîòðåáà. Ïîðàäè òîâà å íàïèñàí è
öèêúëà for, ÷ðåç êîéòî íà âñåêè åëåìåíò íà ia ñå äàâà ñòîéíîñò 0. size, ðàçáèðà
ñå, ñúäúðæà ðàçìåðà íà ìàñèâà.
Ñâîáîäíàòà ïàìåò ñå ðàçïðåäåëÿ ÷ðåç
ïðèëàãàíå íà îïåðàòîðà new êúì äàäåí òèïîâ ñïåöèôèêàòîð, âêëþ÷èòåëíî è êúì èìå
íà êëàñ. Ìîæå äà áúäå îòäåëåíà ïàìåò êàêòî çà åäèíè÷åí îáåêò, òàêà è çà ìàñèâ îò
îáåêòè. Íàïðèìåð,
int *pi = new int;
îòäåëÿ ïàìåò çà åäèí îáåêò îò
òèï int. Îïåðàòîðúò new âðúùà óêàçàòåë êúì òîçè îáåêò è ÷ðåç íåãî ñå
èíèöèàëèçèðà pi.
IntArray *pia = new IntArray( 1024 );
îòäåëÿ
ïàìåò çà îáåêòà êëàñ IntArray. Ñêîáèòå, êîèòî ñà çàïèñàíè ñëåä èìåòî íà êëàñà,
àêî ãè èìà, ñå ÿâÿâàò êàòî àðãóìåíòè íà êîíñòðóêòîðà íà êëàñà.  òîçè ñëó÷àé,
pia ñå èíèöèàëèçèðà êàòî óêàçàòåë êúì îáåêò - êëàñ IntArray ñ 1024 åëåìåíòà. Àêî
ñêîáèòå ëèïñâàò, êàêòî â èçðàçà
IntAarray *pia2 = new
IntArray;
òîãàâà èëè êëàñúò òðÿáâà äà äåôèíèðà êîíñòðóêòîð, êîéòî íå
èçèñêâà àðãóìåíòè èëè äà íå äåôèíèðà êîíñòðóêòîðè èçîáùî.
Íåêà äàäåí
ìàñèâ å ðàçïîëîæåí â ñâîáîäíàòà ïàìåò ïîñðåäñòâîì òèïîâ ñïåöèôèêàòîð ñúñ
çàòâîðåíà â ñêîáè ðàçìåðíîñò. Ðàçìåðíîñòà ìîæå äà áúäå çàäàäåíà ÷ðåç ïðîèçâîëåí
ñëîæåí èçðàç. Îïåðàòîðúò new âðúùà óêàçàòåë êúì ïúðâèÿò åëåìåíò íà ìàñèâà.
Íàïðèìåð,
#include <string.h>
char *copyStr ( const char *s )
{
char *ps = new char[ strlen(s) + 1 ];
strcpy( ps, s );
retunr
ps;
}
Çà ìàñèâèòå êàòî êëàñîâè îáåêòè ìîæå ñúùî äà áúäå îòäåëÿíà
ïàìåò. Íàïðèìåð,
IntArray *pia = new IntArray[ someSize
];
ðàçïîëàãà â ñâîáîäíàòà ïàìåò ìàñèâ, êîéòî å îáåêò íà êëàñà IntArray ñ
íÿêàêúâ ðàçìåð.
Îòäåëÿíåòî íà ïàìåò ïî âðåìå íà èçïúëíåíèå ñå íàðè÷à
äèíàìè÷íî ðàçïðåäåëÿíå íà ïàìåòòà. Êàçâàìå, ÷å ìàñèâúò, àäðåñèðàí ÷ðåç ia, å
ðàçïîëîæåí äèíàìè÷íî. Îòäåëÿíåòî íà ïàìåò çà ñàìèÿ óêàçàòåë ia, îáà÷å, ñå
èçâúðøâà ïî âðåìå íà êîìïèëàöèÿ - òîâà å ïðè÷èíàòà, ïîðàäè êîÿòî ia ìîæå äà áúäå
èìåíóâàí îáåêò. Îòäåëÿíåòî íà ïàìåò ïî âðåìå íà êîìïèëàöèÿ ñå íàðè÷à ñòàòè÷íî
ðàçïðåäåëÿíå íà ïàìåòòà. Êàçâàìå, ÷å óêàçàòåëÿò ia å ðàçïîëîæåí
ñòàòè÷íî.
Âðåìåòî íà ñúùåñòâóâàíå íà åäèí îáåêò, ò.å. òîçè ïåðèîä îò
âðåìå, êîãàòî ñå èçïúëíÿâà ïðîãðàìàòà, ñå íàðè÷à ïåðèîä íà àêòèâíîñò íà îáåêòà.
Çà ïðîìåíëèâèòå, äåôèíèðàíè ñ ôàéëîâ îáõâàò, ñå êàçâà, ÷å ïðèòåæàâàò ñòàòè÷åí
ïåðèîä íà àêòèâíîñò. Çà òÿõ ñå îòäåëÿ ïàìåò ïðåäè çàïî÷âàíå íà èçïúëíåíèåòî íà
ïðîãðàìàòà è òÿ îñòàâà ñâúðçàíà ñ ïðîìåíëèâàòà äîêàòî ïðîãðàìàòà ïðèêëþ÷è
ðàáîòàòà ñè. Çà ïðîìåíëèâèòå, äåôèíèðàíè ñ ëîêàëåí îáõâàò, ñå êàçâà, ÷å
ïðèòåæàâàò ëîêàëåí ïåðèîä íà àêòèâíîñò. Çà òÿõ ñå îòäåëÿ ïàìåò ïðè âñÿêî
íàâëèçàíå â ëîêàëíèÿ èì îáõâàò; íà èçëèçàíå îò íåãî ïàìåòòà ñå îñâîáîæäàâà.
Âñÿêà ëîêàëíà ïðîìåíëèâà static èìà ñòàòè÷åí ïåðèîä íà àêòèâíîñò.
Çà
îáåêòè, ðàçïîëîæåíè â ñâîáîäíàòà ïàìåò, ñå êàçâà, ÷å ïðèòåæàâàò äèíàìè÷åí ïåðèîä
íà àêòèâíîñò. Ïàìåòòà, îòäåëåíà ÷ðåç èçïîëçâàòíåòî íà îïåðàòîðà new îñòàâà
ñâúðçàíà ñ îáåêòà äîêàòî íå áúäå îñâîáîäåíà ÿâíî îò ïðîãðàìèñòà. ßâíîòî
îñâîáîæäàâàíå ñå îñúùåñòâÿâà ÷ðåç ïðèëàãàíåòî íà îïåðàòîðà delete êúì óêàçàòåëÿ,
êîéòî àäðåñèðà äèíàìè÷íèÿ îáåêò. Íåêà ðàçãëåäàìå åäèí ïðèìåð.
IntArray
grow() ðàçøèðÿâà ìàñèâà, àäðåñèðàí ÷ðåç ia, ñ ïîëîâèíàòà îò ðàçìåðà ìó. Ïúðâî,
òðÿáâà äà áúäå îòäåëåíà ïàìåò çà åäèí íîâ ïî-ãîëÿì ìàñèâ. Ñëåä òîâà òðÿáâà äà ñå
êîïèðàò ñòîéíîñòèòå íà ñòàðèÿ ìàñèâ, à äîïúëíèòåëíèòå åëåìåíòè òðÿáâà äà ñå
èíèöèàëèçèðàò ñúñ ñòîéíîñò 0. Íàêðàÿ, ïàìåòòà, çàåòà îò ñòàðèÿò ìàñèâ, òðÿáâà äà
ñå îñâîáîäè ÿâíî ÷ðåç ïðèëàãàíå íà îïåðàòîðà delete.
void IntArray grow()
{
int *oldia = ia;
int oldSize = size;
size += size/2 + 1;
ia = new
int[ size ];// copy elements of old array into new
for ( int i = 0; i <
oldSize; ++i ) ia[ i ] = oldia[ i ];
for ( ; i < size; ++i ) ia[ i ] =
0;
delete oldia;
}
oldia èìà ëîêàëåí ïåðèîä íà àêòèâíîñò; ïàìåòòà,
îòäåëåíà çà íåÿ, ñå îñâîáîæäàâà àâòîìàòè÷íî, êîãàòî èçïúëíåíèåòî íà ôóíêöèÿòà
ïðèêëþ÷è. Òîâà íå ñå îòíàñÿ, îáà÷å, çà àäðåñèðàíèÿ îò oldia ìàñèâ. Íåãîâèÿò
ïåðèîä íà àêòèâíîñò å îò äèíàìè÷åí òèï è ïðîäúëæàâà äà ñúùåñòâóâà è èçâúí
ãðàíèöèòå íà ëîêàëíèÿ îáõâàò. Àêî ïàìåòòà, îòäåëåíà çà ìàñèâà, àäðåñèðàí ÷ðåç
oldia, íå áúäå îñâîáîäåíà ÿâíî, êàòî ñå èçïîëçâàò îïåðàòîðà delete, òÿ îñòàâà
ïðèñúåäèíåíà êúì ïðîãðàìàòà. delete oldia; îñâîáîæäàâà, îòäåëåíàòà çà ìàñèâà
ïàìåò.
Êîãàòî èçòðèâàìå ìàñèâ, êîéòî å êëàñîâ îáåêò, íà îïåðàòîðà delete
òðÿáâà äà å èçâåñòåí ðàçìåðà ìó. Òîâà å íåîáõîäèìî çà äà áúäå èçâèêàí ïîäõîäÿùèÿ
êëàñîâ äåñòðóêòîð. Íàïðèìåð, äàäåí å ñëåäíèÿ ìàñèâ
IntArray *pia = new
IntArray[ size ];
Òîãàâà îïåðàòîðúò delete, ïðèëîæåí êúì pia èçãëåæäà
òàêà
delete [size] pia;
Îïåðàòîðúò delete òðÿáâà äà áúäå ïðèëàãàí
ñàìî çà ïàìåòòà, êîÿòî å áèëà îòäåëåíà ÷ðåç îïåðàòîðà new. Ïðèëàãàíåòî íà
îïåðàòîðà delete êúì ïàìåò, êîÿòî íå å îòäåëåíà îò ñâîáîäíàòà ïàìåò âåðîÿòíî ùå
ñå ïðîÿâè â íå äåôèíèðàíîòî ïîâåäåíèå íà ïðîãðàìàòà ïî âðåìå íà èçïúëíåíèå.
Ïðèëàãàíåòî íà îïåðàòîðà delete âúðõó óêàçàòåë ñúñ ñòîéíîñò 0, îáà÷å, íå
ïðåäèçâèêâà íèêàêâè îïàñíè ïîñëåäèöè - ò.å. êúì óêàçàòåë, êîéòî íå àäðåñèðà
îáåêò. Ñëåäâàò íÿêîëêî ïðèìåðà çà áåçîïàñíî è íå áåçîïàñíî ïðèëàãàíå íà
îïåðàòîðà delete
void f(){
int i;
char *str = "dwarves";
int *pi
= &i; // dangerous delete pi;
intArray *pia = 0; // dangerous delete
pia;
doduble *pd = new double;
delete str;
}
Ñâîáîäíàòà ïàìåò íà
ïðîãðàìàòà íå å áåçêðàéíà; ïðåç âðåìåòî íà èçïúëíåíèå íà ïðîãðàìàòà òÿ ìîæå äà
áúäå èç÷åðïàíà. (Ðàçáèðà ñå, àêî îáåêòèòå, êîèòî íå ñà íåîáõîäèìè ïîâå÷å, íå
áúäàò èçòðèòè, ùå ñå óâåëè÷è ñêîðîñòòà íà èç÷åðïâàíå íà ñâîáîäíàòà ïàìåò). Ïî
ïîäðàçáèðàíå, new âðúùà 0, êîãàòî íàëè÷íàòà ñâîáîäíà ïàìåò íå å äîñòàòú÷íà çà äà
óäîâëåòâîðè çàÿâêàòà.
Ïðîãðàìèñòúò íå ìîæå ñïîêîéíî äà èãíîðèðà
âúçìîæíîñòòà, êîãàòî new âðúùà 0. Íàøàòà ôóíêöèÿ grow(), íàïðèìåð, íÿìà äà
ðàáîòè àêî new íå å â ñúñòîÿíèå äà îòäåëè èñêàíàòà ïàìåò. Äà ïðèïîìíèì, ÷å
íàøèÿò òåêñò èçãëåæäàøå òàêà
ia = new int[ size ]; // trouble
if new
returns 0
for ( int i = 0; i < oldSize; ++i )
ia[ i ] = oldia[ i
];
Ïðîãðàìèñòúò òðÿáâà äà ïðåäîòâðàòè èçïúëíåíèåòî íà öèêúëà for, êîãàòî
ia èìà ñòîéíîñò 0. Íàé-ïðîñòèÿò ìåòîä çà äà áúäå íàïðàâåíî òîâà, å äà ñå äîáàâè
îïåðàòîð çà ïðîâåðêà íà ñòîéíîñòòà íà ia, êîéòî äà ñëåäâà îáðúùåíèåòî êúì new.
Íàïðèìåð,
ia = new int[ size ];
if ( !ia ){
error("IntArray
grow()
free store exhausted");
}
êúäåòî error()
å åäíà îáùà ôóíêöèÿ, äåôèíèðàíà îò ïðîãðàìèñòà è ïðåäíàçíà÷åíà äà ñúîáùàâà çà
ãðåøêè êàòî îñèãóðÿâà åëåãàíòåí èçõîä.
Åòî åäíà ìàëêà ïðîãðàìà, êîÿòî
èëþñòðèðà èçïîëçâàíåòî íà grow()
#include <stream.h>
#include
"IntArray.h"
IntArray ia[ 10 ];
main() {
cout << "size "
<< ia.getSize() << "n";
for ( int i = 0; i < ia.getSize();
++i )
ia[i] = i*2; // initialize ia.grow();
cout << "new size "
<< ia.getSize() << "n";
for ( i = 0; i < ia.getSize(); ++i
)
cout << ia[i] << " ";
}
Êîãàòî òàçè ïðîãðàìà áúäå
êîìïèëèðàíà è èçïúëíåíà, ñå ïîëó÷àâà ñëåäíèÿ ðåçóëòàò
size 10
new
size
16 0 2 4 6 7 10 12 14 16 18 0 0 0 0 0 0
Åòî åäíà ôóíêöèÿ, êîÿòî å
ïðîåêòèðàíà äà èëþñòðèðà èç÷åðïâàíåòî íà ñâîáîäíàòà ïàìåò. Òÿ å ðåàëèçèðàíà êàòî
ðåêóðñèâíà ôóíêöèÿ, ÷èåòî óñëîâèå çà ñïèðàíå å âðúùàíåòî íà ñòîéíîñò 0 îò
new
#include <stream.h>
viod exhaustFreeStore( unsigned long
chunk ) {
static int gepth = 1;
static int report = 0;
++depth; // keep
track of invocations
double *ptr = new double[ chunk ];
if ( ptr
)
exhaustFreeStore( chunk );// free store exhausted
delete ptr;
if (
!report++)
cout << "Free Store Exhausted" << "tchunk " <<
chunk
<< "depth " << depth <<
"n";
}