Программирование >>  Дополнительные возможности наследования 

1 ... 77 78 79 [ 80 ] 81 82 83 ... 265


15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

int itsAge; int itsWeight;

SimpleCat:;SimpleCat(int age, int weight) {

itsAge = age; itsWeight = weight;

SimpleCat &TheFunction();

int main() {

SimpleCat &rCat = TheFunction(); int age = rCat. GetAgeO; cout rCat age years olcl!\n return 0; }

SimpleCat &TheFunction() {

SimpleCat Frisky(5,9); return Frisky;

Compile error: Attempting to return a reference to a local object! (Ошибка компиляции: попытка возвратить ссылку на локальный объект!)

IPEiyiPEIIEIIE

Эта программа не компилируется на компиляторе фирмы Borland, но для нее подходят компиляторы компании Microsoft. Однако профессиональный программист никогда не станет полагаться на уступки компилятора.

В строках 7-17 объявляется класс SimpleCat. В строке 29 инициализируется ссылка на объект класса SimpleCat с использованием результатов вызова функции TheFunctionO, объявленной в строке 25. Согласно объявлению эта функция возвращает ссылку на объект класса SimpleCat.

В теле функции TheFunctionO объявляется локальный объект типа SimpleCat и инициализируется его возраст и вес. Затем этот объект возвращается по ссылке. Некоторые компиляторы обладают достаточным интеллектом, чтобы распознать эту ошибку, и не позволят вам запустить данную программу на выполнение. Другие же (сразу видно, кто настоящий друг) спокойно разрешат вам выполнить эту программу с непредсказуемыми последствиями.

По возвращении функции TheFunctionO локальный объект Frisky будет разрушен (надеюсь, безболезненно для самого объекта). Ссылка же, возвращаемая этой функцией, останется псевдонимом для несуществующего объекта, а это явная ошибка.



Возвращение ссылки на оОъект в оОластн динамического оОмена

Можно было бы попытаться решить проблему, представленную в листинге 9.13, сориентировав функцию TheFunction() на размещение объекта Frisky в области динамического обмена. В этом случае после возврата из функции TheFunction() объект Frisky будет все еще жив.

Новый подход порождает новую проблему: что делать с памятью, вьщеленной для объекта Frisky, после окончания обработки этого объекта? Эта проблема показана в листинге 9.14.

Листинг В.14. Утечка намята

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

Листинг 9.14,

Разрешение проблемы утечки памяти Sinclude <iostream.h>

class SimpleCat {

public:

SimpleCat (int age, int weight); SimpleCatO { }

int GetAgeO { return itsAge; } int GetWeightO { return itsWeight; }

1 2 3 4 5 6 7 8 9

10 11 12

13 private:

14: int itsAge;

int itsWeight;

SimpleCat::SimpleCat(int age, int weight) {

itsAge = age; itsWeight = weight;

SimpleCat & TheFunction();

int mainO {

SimpleCat & rCat = TheFunction();

int age = rCat.GetAgeO;

cout rCat age years old!\n

cout &rCat: &rCat endl;

Как освободить эту память?

SimpleCat * pCat = &rCat;

delete pCat;



35 36 37 38 39 40 41 42 43

Боже, на что же теперь ссылается rCat?? return 0; }

SimpleCat &TheFunction() {

SimpleCat pFrisky = new SimpleCat(5,9); cout pFrisky: << pFrisky endl; return pFrisky;

pFrisky: 0x0043lC60 rCat 5 years old! &rCat: 0x00431060


предупреждение

Эта программа компилируется, компонуется и, кажется, работает. Но мина замедленного действия уже ожидает своего часа.

. Функция TheFunctionO была изменена таким образом, чтобы больше не возвращать ссылку на локальную переменную. В строке 41 выделяется некоторая область динамически распределяемой памяти и ее адрес присваивается указателю. Этот адрес выводится на экран, после чего указатель разыменовывается и объект класса SimpleCat возвращается по ссылке.

В строке 28 значение возврата функции TheFunctionO присваивается ссылке на объект класса SimpleCat, а затем этот объект используется для получения возраста кота, и полученное значение возраста выводится на экран в строке 30.

Чтобы доказать, что ссылка, объявленная в функции main(), ссылается на объект, размещенный в области динамической памяти, вьщеленной для него в теле функции TheFunctionO, к ссылке rCat применяется оператор адреса (&). Вполне убедителен тот факт, что адрес объекта, на который ссылается rCat, совпадает с адресом объекта, расположенного в свободной области памяти.

До сих пор все было гладко. Но как же теперь освободить эту область памяти, которая больше не нужна? Ведь нельзя же выполнять операции удаления на ссылках. На ум приходит одно решение: создать указатель и инициализировать его адресом, полученным из ссылки rCat. При этом и память будет освобождена, и условия для утечки памяти будут ликвидированы. Все же одна маленькая проблема остается: на что теперь ссылается переменная rCat после выполнения строки 34? Как указывалось выше, ссылка всегда должна оставаться псевдонимом реального объекта; если же она ссылается на нулевой объект (как в данном случае), о корректности программы говорить нельзя.

примечание

Не будет преувеличением определение программы как некорректной, если она содержит ссылку на нулевой объект (несмотря на то что она успешно компилируется), поскольку результаты ее выполнения непредсказуемы.



1 ... 77 78 79 [ 80 ] 81 82 83 ... 265

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика