Помогни ни да направим Uroci.net по - богат! Добави урок

C++ част.4 (Функции и обхват)

C++ » C++
fix3d   трудност:    видян: 42384



4.10. Локален обхват

Най-общо казано, за локалните променливи се отделя памет при обръщението към функцията; за тях се казва, че “идват във” или че имат “входен обхват”. Тази памет се отделя по време на изпълнение от програмния стек и е част от записа за активиране на функцията. Една неинициализирана локална променлива ще съдържа случайна стойност, според битовата последователност, записана в паметта при предишното й използуване. За тази стойност се казва, че не е дефинирана. Когато една функция приключи работата си, от програмния стек се отстранява записа й за активиране. По такъв начин паметта, свързана с локалните променливи се освобождава. Казва се, че променливите “излизат вън” или, че имат “изходен обхват” при приключване на изпълнението на функцията. Стойностите, които те съдържат, се загубват.

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

#include <streama.h>
const strLen = 8;
char *globalString;
char *trouble() {
char localString[ strLen ];
cout << "Enter string ";
cin >> localString;
return localString; // dangerous
}

main() { globalString = trouble(); ... }

globalString съдържа адреса на локален масив от символи localString. За нещастие, обаче, паметта, отделена за localString се освобождава, когато функцията trouble() приключи изпълнението си. Когато се върнем отново в main(), globalString фактически адресира неизползувана памет.

Когато адресът на дадена локална променлива се изпраща вън от обхвата й се казва, че става дума за “висящ указател”. Това е една сериозна програмна грешка, понеже съдържанието на адресираната памет е непредсказуемо. Ако битовете на този адрес се окажат сравнително подходящи, програмата може да се изпълни до край, но да даде грешни резултати.

Локалните обхвати могат да бъдат влагани. Всеки блок, който съдържа декларативни оператори поддържа свой собствен локален обхват. Например, следната част от програма дефинира две нива на локален обхват, реализирайки двоично търсене в сортиран масив.

const notFound = -1;
int binSearih( int *ia, int sz, int val ) {
// local scope level #1// contains ia, sz, val, low, high
int low = 0;
int high = sz - 1;
while ( low <= high ) {
// local scope level #2
int mid = ( low + high )/2;
if ( val == ia[ mid ] )
return mid;
if ( val < ia[ mid ] ) high = mid - 1;
else low = mid + 1;
} // end, local scope level #2
return notFound;
} // end, local scope level #1

Цикълът while от binSearch() дефинира вложен локален обхват. Той съдържа един идентификатор, идентификатора mid, затворен в локалния обхват на binSearch(). Той съдържа аргументите ia, sz и val, както и локалните променливи high и low. Глобалният обхват затваря и двата локални обхвата. Той съдържа един идентификатор, цялата константа notFound.

Когато е създаден псевдоним на даден идентификатор се търси непосредственият обхват, в който се явява псевдонима. Ако е намерена дефиниция на идентификатора, псевдонимът се свързва с нея; иначе се търси в по-голям обхват. Този процес продължава или докато псевдонимът се свърже с идентификатора или докато бъде изчерпан и глобалния обхват. Ако се случи последното, псевдонимът се отбелязва като неправилно дефиниран.

Използуването на оператора за обхват (“ “) ограничава търсенето до глобален обхват.

Един цикъл for разрешава дефинирането на променливи в управляващата си структура. Например,

for ( int i = 0; i < arrayBound; ++i )

Променливите, дефинирани в управляващата част на цикъла for, се включват в същия обхват, в който е и самият оператор for. Нека операторът for е записан така:

int i;
for ( i = 0; i < arrayBound; ++i )

Това осигурява достъп на програмиста до управляващите променливи

след приключване на изпълнението на цикъла. Например:

const notFound = -1;
findElement( int *ia, int sz, int val ) {
for ( int i = 0; i < sz, ++i )
if ( ia[ i ] == val ) break;
if ( i == sz ) return notFound;
return i;
}

Това не разрешава на програмиста, обаче, да използува отново имената на управляващите променливи в същия обхват. Например,

fooBar( int *ia, int sz ) {
for (int i=0; i<sz; ++i) ... // defines i
for (int i=0; i<sz; ++i) ... // error i redefined
for (i=0; i<sz; ++i) ... // ok
}


Страници: «8 9 10 11 12 »

Сподели урока:



Регистрирайте се, за да добавите коментар


Калдейта Ком ЕООД - © 2003-. Всички права запазени.
Препоръчваме: IT Новини