Функции. Основные принципы структурной методологии. Принцип формальности. Принцип иерархического упорядочивания, страница 12

При определении ссылок должна присутствовать их инициализация, однако  в описаниях ссылок инициализация не обязана присутствовать. Например:

float& ref;                               //ошибка – нет инициализации

extern  float&   ref2                   //допустимо – инициализируется в другом месте

double E = 2.718282;       //определение переменной

double& eRef = E;           //определение и инициализация ссылки

В спецификации ссылки как формального параметра инициализация необязательна, однако она не запрещена. Сложность состоит в том, что объект, имя которого используется для инициализации параметра-ссылки, должен быть известен при определении функции. Иначе параметр должен быть ссылкой на константу, и с его помощью можно будет передавать значения только внутрь функции, а не из нее.

Рассмотрим пример:

#include <iostream.h>

int n=-55;

void invert(int& k=n)      //определение функции с инициализацией параметра-ссылки

{ cout << “\n invert() k=”;

cout << k;

k = -k;

}

void main()

{int a=22, b=66;

invert();                             //k=-55;  n=55;

cout << “\n n= ” << n;

invert(a);                           //k=22;  a=-22;

cout << “\n a= ” << a;

//invert(a+b);                  //ошибка компиляции: выражение не имеет адреса

//cout << “\n a= ” << a << “b=  ” << b;

double d=3.33;

//invert (d);                     //ошибка компиляции

//замена на оператор à invert (reinterpret_cast < int&> (d));

//обеспечивает результаты, приведенные ниже,

// т.е. значение d не инвертируется

cout << “\n d=  ” << d;

cout << endl;

}

Результат работы программы:

invert() k=-55

n= 55

invert() k=22

a= -22

invert() k=171798692

d=  3.33

Пример демонстрирует особенности передачи параметров в функцию через ссылки по сравнению с передачей параметров через указатели:

#include <iostream.h>                          

void changePtr (double *a, double *b)

{double c=*a;

*a=*b;

*b=c;

}

void changeRef (double& x, double& y)

{double z=x;

x=y;

y=z;

}

void main()

{double d=1.23;

double e =4.56;

changePtr(&d, &e) ;

cout << "\nd=   " << d << "\t\te=" << e ;

changeRef(d, e) ;

cout << "\nd=   " << d << "\t\te=" << e ;

cout << endl;

}

Результаты работы программы:

d=   4.56               e=1.23

d=   1.23               e=4.56

Пример функции, возвращающей ссылку как результат своей работы:

#include <iostream.h>

int x;                        // глобальная переменная

int& setx();              // прототип функции

int main()

{                    

setx() = 92;           // функция вызывается из левой части оператора присваивания

cout << "x=" << x << endl;    // вывод нового значения глобальной переменной

return 0;

}

//-------------------------------------------------------------int&  setx()

{

return x;             // возвращает ссылку на х

}

Пример использования функции atexit() для обработки завершения программы:

В качестве функции обработки завершения программы, имя которой передается функции  atexit(),рассмотрим функцию adder(), выводящую текущие дату и время:

#include <iostream.h>

#include <stdlib.h>           //для atexit()

#include <time.h>             //для time(), сtime(), clock()  иCLOCKS_PER_SEC

void adder  (void);  //прототип функции, объявленной для завершения программы

main()

{ atexit(adder);   //вызов функцииatexitрегистрируетadderв качестве                                 // функции, завершающей работу программы

  //…..операторытела функцииmain

return 0;

}

void adder (void)  //определение функции завершения программы, которая

{ long t;                       // не должна иметь параметров и возвращаемого значения