/* Передача существующего объекта */
cout << "Вызов someFn( Student
& )\n" ; someFn( s ) ;
cout << "Возврат из someFn ( Student
& )\n" ;
/* Значение s.gpa теперь равно 3.0 */
cout << "Значение s.gpa = " << s.gpa << "\n" ;
/* Пауза для того, чтобы посмотреть на результат работы программы */
system( "PAUSE" ) ; return 0 ;
}
Значение s.gpa = 0
Вызов someFn( Student&
) Значение refS.gpa = 3
Возврат из someFn( Student&
) Значение s.gpa = 3
Press any key to continue...
В этой программе в функцию someFn( )
передаётся не копия объекта, а ссылка на него. Изменения, внесённые функцией someFn( ) в s, сохраняются внутри main( ).
«Передача объекта по ссылке — всего лишь другой способ передачи в функцию адреса объекта
s. С++ самостоятельно отслеживает адрес ссылки, в то время как при передаче указателя вы должны заниматься этим сами.» [
Советы]►Зачем, использовать указатели и ссылки...174
Итак, передать объект в функцию можно разными способами. Но почему бы нам не ограничиться одним, простейшим способом — передачей по значению?
Один ответ мы уже получили, когда изучали способы передачи в этой главе, — при передаче по значению вы не можете изменить исходный объект, поскольку в функции работаете с копией объекта.
А вот и вторая причина — некоторые объекты могут оказаться действительно очень большими. Передача такого объекта по значению приводит к копированию большого объёма информации в память функции.
«Область, используемая для передачи аргументов функции, называется стеком вызова.»
[
Технические подробности]При вызове из функции другой функции объект копируется вновь, и в результате нескольких вложенных вызовов вы получите десяток объектов в памяти и программу, работающую медленнее загрузки Windows.
«Проблема на самом деле ещё сложнее, чем описано здесь. В главе 18, "Копирующий конструктор"
, вы убедитесь, что создание копии объекта представляет собой существенно более сложную задачу, чем простое копирование участка памяти из одного места в другое.»[
Атас!]_________________
174 стр. Часть 3
. Введение в классы
►Возврат к куче...175
Проблемы, возникающие при работе с указателями на простые переменные, распространяются и на указатели на объекты. В частности, необходимо гарантировать, что указатель ссылается на существующий корректный объект. Так, нельзя возвращать указатель на локально определённый объект, как это сделано в данном примере:
MyClass* myFunc( )
{
/* Эта функция не будет работать правильно */
MyClass mc ;
MyClass* рМС =
&mc ; return рМС ;
}
После возврата из myFunc( )
объект mc выходит из области видимости, а значит, указатель, который возвращает myFunc( ), указывает на несуществующий объект.
«Проблемы, связанные с возвратом памяти, которая выходит из области видимости, рассматривались в главе 9, "Второе знакомство с указателями"
.»[
Помни!]Использование кучи позволяет решить эту проблему:
MyClass* myFunc( )
{
MyClass* рМС = new MyClass ;
return рМС ;
}
«С помощью кучи можно выделять память для объектов в самых разнообразных ситуациях.»
[
Помни!] ►Сравнение указателей и ссылок...175
Очень часто новички в программировании спрашивают, зачем нужны и указатели, и ссылки, и нельзя ли обойтись чем-то одним?