Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
Использование ссылки вместо передачи по значению более эффективно, поскольку
не требует копирования параметров, что имеет значение при передаче структур данных большого объема.
В случае вызова по ссылке оператор вызова дает вызываемой функции возможность прямого доступа к передаваемым данным, а также изменения этих данных, что может ослабить защищенность, поскольку вызываемая функция может испортить передаваемые в нее данные.
Ссылочный параметр в прототипе функции определяется знаком &.
Написать функцию возведения числа в квадрат:
int VKv(int & a)
{
return a*a;
}
или
void VKv(int & a, & aa)
{
aa=a*a; a=1;
}
void main(void)
{
int a =2;
int b;
b = VKv(a); //b=4
VKv(a, c); //c=4
VKv(a, c); //c=4
}
Для того, чтобы уменьшить накладные расходы и в то же время не иметь возможности в функции изменять исходные значения (повысить защищенность) можно использовать константный ссылочный тип.
void VKv(const int & a, int & aa) //int aa - ошибка
{
aa=a*a;
//a=2;
}
Если требуется запретить изменение параметра внутри функции, используется модификатор const. Рекомендуется использовать модификатор const перед всеми параметрами, изменение которых в функции не предусмотрено.
Например, функция для вычисления площади круга:
const double M_PI = 3.1415926;
float SKr(const float R)
{
return R*R*M_PI;
}
Входные данные — R. Выходные данные — то, что после return.
M_PI — неизменяемая переменная, типа double.
В резульате s=SKr(2) s=8.2548E08
#include <iostream. h>
#include <iomanip. h>
int VKub(int * a)
{
return *a * *a * *a;
}
void VKub(const int * a, int * aa)//нельзя изменить значение
//переменной a
{
*aa = *a * *a * *a;
*a=2; //ошибка компиляции
}
void main(void)
{
int a =2;
int b, c;
b = VKub(&a); //b=8
VKub(&a, &c); //c=8
}
void VKub(const int * a, int * aa) //нельзя изменить значение переменной a
*a=0 - ошибка
a=....; //можно
void VKub(int * const a, int * aa) //нельзя изменить значение указателя a
a=222;-ошибка
*a=2; //можно
void VKub(const int * const a, int * aa)
Пример. Написать функцию для обмена элементов массива m с номерами i и j.
void Swap3(int * mi, int * mj) //можно по указателям на элементы
{
int tmp=*mi;
*mi=*mj;
*mj=tmp;
}
void Swap4(int m[], int i, int j) //можно по указателю на массив
{ //с нотацией массива
int tmp=m[i];
m[i]=m[j];
m[j]=tmp;
}
void Swap5(int *m, int i, int j) //можно по указателю на массив
{ //с нотацией указателя
int tmp=*(m+i);
*(m+i)=*(m+j);
*(m+j)=tmp;
}
Вызов этих функций осуществляется следующим образом
void main (void)
{
int m[6]={1,2,3,4,5,6};
Swap3(&m[2], &m[4]);
Swap3(m+2, m+4);
Swap4(m, 2, 4);
Swap5(m, 2, 4);
}
Перегрузка функций
------------------
В С++ имеется возможность определять несколько функций с одинаковым именем, если эти функции имеют разные типы параметров или разное их количество. Это удобно если функции имеют сходные задачи, но разные типы данных.
Например, в программе можно написать 2 функции для нахождения минимального среди 2 или трех чисел
#include <iostream. h>
double min(double a, double b)
{
if (a<b) return a;
else return b;
}
double min(double a, double b, double c)
{
if (a<=b) && (a<=c) return a;
if (b<=a) && (b<=c) return b;
if (c<=a) && (c<=b) return c;
}
void main(void)
{
int i=5, j=6, k=2;
cout << min(i, j); //5
cout << min(i, j, k); //2
cout << min(1, 6, k); //1
}
или
int kv(int k)
{
return k*k;
}
double kv(double y)
{
return y*y;
}
Ссылки
--------
Ссылка представляет собой синоним имени, указанного при
инициализации ссылки.
int kol;
int & pal = kol;
pal — ссылка, она всегда равно содержимому kol, поскольку pal и kol ссылаются на одну область памяти. В ходе выполнения программы ссылка pal будет всегда ссылаться на переменную kol (то есть ссылке не может быть присвоена другая переменная).
Если присвоить pal = 4;, то kol тоже будет равна 4 и наоборот.
Ссылки применяются чаще всего только в качестве параметров функций и типов, возвращаемых функциями значений.
Ссылки позволяют использовать в функции переменные, передаваемые по адресу без операции разадресации, что улучшает читаемость программы.
Swap2 после компиляции — точный аналог Swap3.
void Swap2(int & mi, int & mj) //можно по ссылке на элементы
{
int tmp=mi;
mi=mj;
mj=tmp;
}
void Swap1(int mi, int mj) //нельзя - вызов по значению
{
int tmp=mi;
mi=mj;
mj=tmp;
}
void main ()
{
int m[10]={1, 2, 3}, i=2, j=4;
Swap1(m[i], m[j]); //нельзя
Swap2(m[i], m[j]); //можно
Swap3(&m[i], &m[j]); //можно
Swap4(m, i, j);
Swap5(m, i, j);
}
К третьему элементу массива
int m[5]
можно обращаться m[2] — нотация массива;
*(m+2) — нотация указателя.
*m ===== m[0] ==== *(m+0)
*(m+1) ==== m[1]
m[0]=1; m[1] = 2; m[3]=4;
m == &m[0] === 50000 - адрес ячейки памяти, где находится m[0].
&m[1] === m+1 ==== 50002.
&m[2] === m+2 ==== 50004.
То есть
int m[5];
cout << m; // 50000
++m;
cout << m; // 50002
++m;
cout << m; // 50004
и т. д.
double md[5];
cout << md; // 60000
++md;
cout << md; // 60008
++md;
cout << md; // 60016
Шаблоны функций
----------------
Шаблоны функций позволяют написать одну функцию таким
образом, чтобы она могла работать с переменными разных типов, например:
вместо функций
int sum(int & a, int & b)
{
return a+b;
}
double sum(double & a, double & b)
{
return a+b;
}
string sum(string & a, string & b)
{
return a+b;
}
complex sum(complex & a, complex & b)
{
return a+b;
}
можно написать всего одну функцию-шаблон с требующим уточнения типом
(Реализация шаблона-функции помещается в *.h файле.)
template <class T>
T sum(T & a, T & b)
{
return a + b;
}
Пример вызова шаблона-функции:
void main(void)
{
string a, b;
int i, j;
double d1, d2, d3;
complex c1, c2, c3;
cout << sum<string>(a, b) << endl;
//при необходимости или по желанию следует уточнять тип
cout << sum(i, j) << endl;
c3 = sum(c1, c2);
d3 = sum(d1, d2);
}
Например функция, меняющая значения двух переменных любых типов:
template <class T>
void swap(T & a, T & b)
{
T c;
c = a;
a = b;
b = c;
}
Передача массивов в функции
----------------------------
При использовании в качестве параметра массива в функцию передается указатель на его первый элемент, иными словами массив передается по адресу. При этом информация о количестве элементов массива теряется, и следует передавать его размерность через отдельный параметр.
Чтобы передать массив в качестве аргумента в функцию достаточно указать имя массива.
Пример. Функция MassOut должна вывести на экран элементы массива:
#include <iostream. h>
#include <iomanip. h>
#include <stdlib. h>
void MassOut(double m[], int n)
{
for (int i=0; i<n; i++)
cout << setprecision(3) << setiosflags(ios::fixed | ios::showpoint)
<< m[i] << " ";
}
void main(void)
{
double m[7]={2.0, 3.444, 5.43, 3.21};
MassOut(m, 7);
}
На экран будет выведено: 2.000 3.444 5.430 3.210 0.000 0.000 0.000
Передача количества элементов массива в функцию необходима, поскольку программно невозможно узнать количество элементов в массиве.
Написать функцию, увеличивающую все элементы массива в 2 раза:
void Mass2(double m[], int n)
{
for (int i=0; i<n; i++)
m[i] *=2;
}
В данном примере переданный в функцию массив должен модифицироваться. Если модифицировать массив в функции не нужно, то лучше обезопаситься от ошибки и передать массив в функцию как const.
void MassOut(const double m[], const int n)
{
for (int i=0; i<n; i++)
cout << setprecision(3) << setiosflags(ios::fixed | ios::showpoint)
<< m[i] << " ";
m[1] *=2; //ошибка при компиляции
}
Пример. Имеется массив с шестью элементами m[6]. Имея функцию
int SumMass(int m[], int n)
{
int s=0;
for (i=0; i<n; i++)
s += m[i];
}
найти сумму s1 = m[0] + m[1] + m[2] + m[3] и
s2 = m[3] + m[4] + m[5].
void main(void)
{
int m[6]= { 2, 2, 3, 4, 5, 6 };
SumMass(m, 4); //сумма s1
SumMass(&m[3], 3); //сумма s2 SumMass(m+3, 3);
}
Передача двумерного массива в функцию
Пример. Распечатать двумерный статический массив с помощью функции.
#include <iostream. h>
#include <iomanip. h>
void MassOut(int m[][3], int r)
{
int i, j;
for (i=0; i<r; i++)
{
cout << endl;
for(j=0; j<3; j++)
cout << setw(7) << m[i][j]; //Ни в коем случае не пишите [i, j]
}
cout << endl;
}
void main(void)
{
int mas1[2][3] = {{1}};
int mas2[3][3] = {{1, 2, 3},{4}};
MassOut(mas1, 2);
MassOut(mas2, 3);
}
1 0 0
0 0 0
1 2 3
4 0 0
0 0 0
Аргумент функции, соответствующий двумерному массиву, имеет вид int m[][3], то есть необходимо передавать массивы с 3 столбцами. Указывать количество столбцов при объявлении функции необходимо для правильного поиска элементов двумерном массиве.
Элементы массива расположены в памяти последовательно
m[0][0] m[0][1] m[0][2] m[1][0] m[1][1] m[1][2] m[2][0] m[2][1] m[2][2]
Таким образом, чтобы обратиться к элементу m[1][2] необходимо взять элемент шестой = 1*3+2. В общем случае элемент m[i][j] расположен в позиции i*<кол_во_столбцов>+j. То есть в формулу входит величина <кол_во_столбцов>, которая и сообщается функции в виде int m[][3].
Функция MassOut может выводить массив только с тремя столбцами, но любым количеством строк. То есть функция не универсальная.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |


