Глава 7. Указатели и ссылки__________________________________763
! Предупреждение
Перед тем как вы начнете конструировать и использовать свои собственные классы, настоятельно рекомендуем вам прочитать и как следует усвоить процедуру передачи объектов в качестве аргументов функций (см. главу 17). Незначительные упущения могут привести к обильным утечкам памяти в ваших программах.
Передача по ссылке
Операции * или & в объявлении функции дают понять, что эта функция способна изменять значение аргументов. Иногда это именно то, что вам нужно, но иногда эффективнее передача по ссылке или передача адреса (детальное рассмотрение особенностей передачи объектов ищите в главе 17). Сейчас нас интересует вопрос, как дать функции возможность модифицировать состояние некоторой переменной, определенной вне ее.
Замечание
*
Что означает вызвать функцию? У функций есть конкретное местоположение в памяти, т. е. адрес. Чтобы исполнить код функции, компилятор сохраняет текущее состояние программы, загружает адрес функции в определенные регистры и выполняет ассемблерную команду call.
Когда аргументы передаются функции, их значения строго определенным образом записываются в стек. Манипуляции со стеком — это забота компилятора, большинство задач, за исключением отдельных задач системного программирования, от вас этого не потребуют.
Адрес аргументов. Операция получения адреса (&) в интерфейсе функции означает, что этот аргумент передается в функцию по ссылке. Фактически функции передается адрес объекта — помните, что под словом объект может подразумеваться переменная как производного, так и базового типа.
Все переменные размещены в памяти, что означает, что у всех у них есть адрес. Взаимосвязь между объектом и его адресом состоит в том, что действия, производимые над объектом по его физическому местоположению — адресу в памяти — ничуть не менее реальны, чем при непосредственном обращении к нему. Если вы хотите, чтобы ваша оператор-функция или просто старая добрая функция изменили значение объекта, то его следует передавать по ссылке. Это достигается вставкой между типом и именем переменной знака s. Пример обеих разновидностей функции со ссылочными аргументами:
void SetValue( int Sval); // по ссылке
Это традиционная функция, получающая адрес целочисленной переменной. А вот пример объявления оператор-функции « для объектов STRING.
ostream &operator«(ostream &os,
STRING &str); // ostream по ссылке