- •Функции
- •1. Определение, описание и вызовы функций
- •Тело функции
- •Формальные параметры:
- •Глобальные переменные:
- •Return (выражение);
- •Void r ( int a, int b, int c)
- •Void main ( )
- •Void rr ( int* a, int* b, int*c)
- •Void main ( )
- •Void rrr ( int & a , int &b , int & c )
- •Void main ( )
- •2. Классификация формальных параметров
- •1) Формальные параметры функции являются:
- •Формальный параметр – скаляр, указатель на скаляр, ссылка на скаляр
- •Void mult ( int a , int b , int *s )
- •Void minmax (int a[n], int & min, int & max)
- •Int main ()
- •2) Формальные параметры - массивы, указатели на массивы
- •Void f1(float a [ ][n][k], int m, float & s)
- •Int main ()
- •Формальный параметр - указатель:
- •Void f (int*a, int*b, int*c, int n, int m)
- •Int main () {
- •Int main ( )
- •Void mas (double** ptr, int m, int n)
- •Int main ( ){
- •Void mas (int (*lp) [3][4], int n)
- •Int main ()
- •3.Результат функции, возвращаемый с помощью оператора return.
- •Return (выражение);
- •Int * poisk (int*c, int m, int n)
- •Int main ()
- •Int main ( )
- •Int main ( )
- •Int main ()
- •Int& rmax (int d [ ], int n)
- •Int main ()
Void r ( int a, int b, int c)
{ a+=100; b+=100; c+=100;
cout << a<<b<<c<<endl ; }
Void main ( )
{ int a1=1, b1=2, c1=3;
cout << a1<<b1<<c1<<endl ;
R ( a1, b1, c1 ) ;
//аналогично можно было вызвать так: R(1, 2 , 3);
// т.к. нас интересуют только значения фактических параметров
cout << a1<<b1<<c1<<endl ;
}
Результат:
1 2 3 // значение переменных до вызова функции
101 102 103 // значения формальных параметров
1 2 3 // значения переменных после вызова функции
// функция не изменила значения переменных, являющимися
//фактическими параметрами
стек
1 2 3 1 2 3
a1 b1 c1 a b c адреса
стек
1 2 3
101 102 103
a1 b1 c1 a b c адреса
Рисунок 1 – Схема обмена данными при передаче параметров по значению
Передача параметров по адресу - по указателю
Формальным параметром является указатель type*p на переменную типа type.
При вызове функции формальному параметру-указателю выделяется память в стеке 4 байта.
Фактическим параметром может быть либо адрес в ОП переменной типа type, либо значение другого указателя, типа type* из вызывающей программы.
В область памяти (в стеке), выделенную для указателя p будет копироваться значение некоторого адреса из вызывающей функции.
В теле функции, используя операцию разыменования указателя *p, можно получить доступ к участку памяти, адрес которого получил p при вызове функции, и изменить содержимое этого участка.
Если в теле функции изменяется значение *p, при вызове функции эти изменения произойдут с тем объектом вызывающей программы, адрес которого использовался в качестве фактического параметра.
Рассмотрим пример передачи параметров по адресу:
. . .
Void rr ( int* a, int* b, int*c)
{ * a+=100; *b+=100 ; * c+= 100 ;
cout << *a << *b << *c ;
}
Void main ( )
{ int a1 =1 , b1= 2 , c1=3 ;
cout << a1 << b1 <<c1 ;
RR ( &a1 , &b1 , & c1 ); //передаем адреса переменных
cout << a1 << b1 <<c1 ;
}
Результат:
1 2 3 // значения переменных до вызова функции
101 102 103 // изменения параметров в функции
101 102 103 // значения переменных после вызова,
// функция изменила их значения
На рисунке 2 показано, как функция изменяет внешние по отношению к ней переменные, используя механизм передачи параметра по адресу.
стек
1 2 3 &a1 &b1 &c1
a1 b1 c1 a b c адреса
( указатели)
cтек
*a+=100
*b+=100
*c+=100
101 102 103 &a1 &b1 &c1
a1 b1 c1 a b c адреса
Рисунок 2 – Схема обмена данными при передаче параметров по адресу
Передача параметров по ссылке
В языке С++ ссылка определена как другое имя уже существующей переменной.
При определении ссылки оперативная память не выделяется.
Инициализатор, являющийся обязательным атрибутом определения ссылки, представляет собой имя переменной того же типа, имеющей место в памяти.
Ссылка становится синонимом этой переменной.
type & имя ссылки = имя переменной;
Основные достоинства ссылок проявляются при работе с функциями.
Если определить ссылку type&a и не инициализировать ее, то это равносильно созданию объекта, который имеет имя, но не связан ни с каким участком памяти. Это является ошибкой.
Однако такое определение допускается в спецификациях формальных параметров функций.
Если в качестве формального параметра функции была определена неинициализированная ссылка - некоторая абстрактная переменная, которая имеет имя, но не имеет адреса, в качестве фактического параметра при вызове функции следует использовать имя переменной из вызывающей программы того же типа, что и ссылка.
Эта переменная и является l-значением и она инициализирует ссылку, т. е. связывает ссылку со своим участком памяти.
Таким образом, ссылка обеспечивает доступ из функции непосредственно к внешнему участку памяти той переменной, которая при вызове функции будет использоваться в качестве фактического параметра.
Все изменения, происходящие в функции со ссылкой, будут происходить непосредственно с переменной, являющейся фактическим параметром.
Это наиболее перспективный метод передачи параметров, так как в этом случае вообще не происходит копирование фактического параметра в стек, будь то значение или адрес, функция непосредственно оперирует с внешними по отношению к ней переменными, используемыми в качестве фактических параметров.
Пример передачи параметров по ссылке:
. . .
