Top Banner
Бублик Володимир Васильович Програмування - 2 Лекція 8. Процедурне програмування. Функції Лекції для студентів 2 курсу
72

08 Functions

Jun 30, 2015

Download

olegapster
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 08 Functions

Бублик Володимир Васильович

Програмування - 2

Лекція 8. Процедурне програмування.

Функції

Лекції для студентів 2 курсу

Page 2: 08 Functions

1. Визначення та виклик функції

Page 3: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

3

Визначення функції

• //Greatest Common Divider• //заголовок• int gcd (int m, int n)• //тіло функції• {• while (m != n)• if (m>n) m=m-n; else n=n-m;• // m == n• //результат• return m;• }

Page 4: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

4

Виклик функції

• int a, b, c;• cin>>a>>b;• c = gcd (a, b); //1. Ініціалізація параметрів• // int m=a; int n=b;• //2. Виконання тіла фукції• //3. Обчислення результату (c=m;)Звичайно виклик функції полягає в припиненні

нормального ходу виконання об'єктного коду, що містить виклик. Відбувається ініціалізація і починає виконуватись об'єктний код функції. Після повернення результату виконання основного коду відновлюється

Page 5: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

5

Способи виконання функцій

Закрита функція• Викликається командою переходу з

поверненнямВідкрита (вбудована) функція• Підставляється в кожне місце виклику

В обох випадках параметри і результат передаються в один і той же спосіб

Page 6: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

6

Вбудовані функції

Об'єктний код закритої функції присутній в програмі один раз. Відповідні команди керування приводять до її активації, виконання коду і наступного повернення в код виклику. Це накладні витрати виклику. Їх можна зменшити, якщо розміщувати код функції безпосередньо в місці виклику. Накладними витратами в цьому разі стане дублювання коду в кожному місці виклику. Компілятор сам приймає рішення, як реалізувати функцію (inline лише порада).

• inline double max(double x, double y)• { return (x>y)?x:y; }

Page 7: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

7

Приблизна схема викликів

• z= max (5, 6);

• z= max(max(1,2),3);

• double x = 5;• double y = 6;• z = (x>y)?x:y;

• double x = 1;• double y = 2;• double x1 = (x>y)?x:y;• double y1 = 3;• z = (x1>y1)?x1:y1;

Page 8: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

8

Макровизначення

Макровизначення на перший погляд дуже схожі на вбудовані функції, вони теж підставляються в місця виклику, але відрізняються від вбудованих функцій способом передачі параметрів текстовою підстановкою.

Приклад макровизначення• #define MAX(x,y) ((x)>(y))?(x):(y)

Приклади макровикликів• MAX(1,2);• MAX(a+b, c-d);

Page 9: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

9

Приклади макропідстановок

• double a = MAX(1,2); //((1)>(2))?(1):(2)• cout<<a<<endl; //2• double b=2;• a= MAX(++a,b); // ((++a)>(b))?(++a):(b) or• // (3>2)?4:2) == 4 • cout<<a<<endl; // 4• // The next expression is not correct• // because of priorities• cout<<MAX(++a,b)<<endl; //means• // cout<<(5>2)?6:4<<endl or• // (cout<<(5>2))?6:(4<<endl) ERROR

Page 10: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

10

Виклик функції

• inline double max(double x, double y)• { return (x>y)?x:y; }

• double a = max(1,2);• // double x=1; double y=2; //ініціалізація параметрів• // return (1>2)?1:2 == 2 виконання тіла і

повернення• cout<<a<<endl; //2• double b=2;• a= max(++a,b);• // double x=++a, double y=b; (x==3, y==2)• // return (3>2)?3:2 == 3

Page 11: 08 Functions

2. Передача параметрів

Page 12: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

12

Передача параметрів

Розглянемо оголошення функції• void f (T x);де f ― ім'я функції, T ― тип параметру, x ― ім'я

параметру

Розглянемо виклик цієї функції• f(e);де e ― вираз підходящого типу (фактичний параметр)

Виконання функції починається визначенням локальної змінної для параметру x з її одночасною ініціалізацією

• T x = e;

Page 13: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

13

Передача параметрів значенням

Ініціалізація• T x = e;говорить про те, що перед виконанням функції

обчислюється значення фактичного параметру е (r-value)

Кажуть, що параметри передаються значеннямЗалежно від типу T ці значення можуть бути 1. значеннями базових типів, структур,2. адресами (у випадку указників)3. відсилками (у випадку псевдонімів)

Page 14: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

14

Сторонній ефект

1. Якщо передаються значення базових типів або структур, то виконання функції не впливає на наступні значення фактичних параметрів

2. Якщо формальний параметр є указником, то можлива зміна значення елементу пам'яті, на який цей указник встановлено

3. Якщо формальний параметр псевдонім, то через нього функція одержує прямий доступ до елементу пам'яті, до якого псевдонім відсилає

Якби не було стороннього ефекту, то який сенс мали б функції виду void f (T x)?

Page 15: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

15

Приклад 1. swap

• void swap( double x, double y)• { // значення базового типу double• double z = x; x=y; y=z;• cout<<x<<‘,’<<y<<endl; //2,1• }

• double a=1, b=2;• swap(a,b);• // double x=a, y=b; • cout<<a<<‘,‘<<b<<endl; // 1,2

Page 16: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

16

Приклад 2. pswap

• void pswap(double *x, double *y)• {• double z = *x; *x=*y; *y=z;• cout<<*x<<‘,’<<*y<<endl; //2,1• }

• double a=1, b=2;• pswap(&a, &b); //за коректність відповідає

користувач• // double *x= &a, *y= &b; • cout<<a<<‘,‘<<b<<endl; // 2,1

Page 17: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

17

Приклад 3. rswap (тільки С++)

• void rswap( double &x, double &y)• {• double z = x; x=y; y=z;• cout<<x<<‘,’<<y<<endl; // 2,1• }

• double a=1, b=2;• rswap(a,b); //за коректність відповідає розробник• // double &x=a, &y=b; • cout<<a<<‘,‘<<b<<endl; // 2, 1

Page 18: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

18

Безпечність виклику

Безпечні• swap(a,b); rswap(a,b);Небезпечний• pswap(&a, &b); // pswap(0, &b); ???

• void pswap(double *x, double *y)• {• assert((x!=0)&&(y!=0));• double z = *x; *x=*y; *y=z;• cout<<*x<<','<<*y<<endl; • }

Page 19: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

19

Масиви як параметри

Масиви ― головна причина використання параметрів-указників

Використання параметром масиву нічим не відрізняється від параметра-указника

• T *a

• T a[]

Page 20: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

20

Задача додому

Що б це значило? Організуйте виклик функції ptrswap та графічно зобразіть роботу з пам'яттю

• void ptrswap( int *&u, int *&v ) • { • int *w = v;• v = u;• u = w;• }

Page 21: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

21

Приклад 4.

Не має значення, як визначити параметр в кожній з трьох сигнатур

• void init (char* ch);

• void show (char ch[]);

• void swapar (char []);

Page 22: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

22

Приклад 4 (1).

• const int n=26;

• int main()• {• char ch[n];• init (ch);• show(ch);• swapar(ch);• show(ch);• return 0;

• }

Page 23: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

23

Приклад 4(2).

• void init(char* ch)• {• for(int i= 'a'; i<'a'+n; i++) //не дуже добре• ch[i-'a'] = i;• }

Ніхто не заборонить навіть таке• for(int i= 'a'; i<'a'+100000; i++)• ch[i-'a'] = i;Результат передбачити неможливо, швидше

всього access violation

Page 24: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

24

Приклад 4(3).

Допустимий навіть зовсім безглуздий виклик

• char ch;• init(&ch);

Теж access violation

Page 25: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

25

Приклад 4’(1).

Краще рішення передати розмір масиву додатковим параметром

• void init (char* ch, int n);

• void show (char ch[], int n);

• void swapar (char [], int);

Page 26: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

26

Приклад 4’(2).

• int main()• {• const int n=26;• char ch[n];• init (ch, n);• show (ch, n);• swapar (ch, n);• show (ch, n);• return 0;

• }

Page 27: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

27

Приклад 4’(2).

• void init (char* ch, size_t n)• {• for(int i= 'a'; i<'a'+n; i++) //тепер в порядку• ch[i-'a'] = i;• }

Page 28: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

28

Приклад 4’(3).

• void show(char ch[n], size_t n)• {• cout<<"start string:"<<endl;• for (int i=0; i<n; i++)• cout<<ch[i]<<' ';• cout<<endl;• }

Page 29: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

29

Приклад 4’(4).

• void swapar(char ch[], size_t n)• {• for (int i = 0; i<n/2; i++)• pswap(ch+i,ch+n-1-i);• };

Page 30: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

30

Приклад 4’(5).

Результат роботи

• start string:• a b c d e f g h i j k l m n o p q r s t u v w x y z • start string:• z y x w v u t s r q p o n m l k j i h g f e d c b a

Page 31: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

31

Висновок

Передаючи в функцію параметром масив (або указник як масив), передбачаємо розмір масиву додатковим параметром

• void f (T *array, size_t size);

або краще• void f (T [] array, size_t size);

Page 32: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

32

“Загорнуті” масиви

// Визначення “загорнутого” вектора

• struct WrappedVector• {• static const int n; //статичне поле одне на

всіх• double * x;• };

// сигнатура добутку (дуже погана)• double prod (WrappedVector, WrappedVector);

Page 33: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

33

Параметри сталі відсилки

// сигнатура добутку (краще)// структури не копіюються• double prod (WrappedVector&, WrappedVector&);

// сигнатура добутку (ще краще)// структури не копіюються,// доступ для зміни фактичного// параметру закрито

• double prod (const WrappedVector&, const WrappedVector&);

Page 34: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

34

Скалярний добуток

// визначення статичного поля структури• const int WrappedVector::n = 100;// визначення скалярного добутку• double prod (const WrappedVector& a,

const WrappedVector& b)• {• double s = 0;• for (int i=0; i<a.n; i++)• s+=a.x[i]*b.x[i];• return s;• }

Page 35: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

35

Створення вектору ― конструктор

// Відсилка ― повний доступ• void construct (WrappedVector &);

• void construct (WrappedVector & a)• {• a.x = new double [a.n];• for (int i=0; i<a.n; i++)• a.x[i] = rand();• return;• }

Page 36: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

36

Видалення об'єкту ― деструктор

• void destroy (WrappedVector& a)• {• delete [] a.x;• a.x = 0;• return;• }

// Як примусити кожного прибирати за собою?

Page 37: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

37

Замовчувані значення параметрів

1. T f (T1 x1=a1, T2 x2=a2, …, Tn xn=an);2. f(); f(c1); f(c1,c2);….

• void createPoint(Point & u, double x=0, double y=0)• {• u._x = x; u._y=y;• }

• createPoint (u); // (0,0)• createPoint (v, 1);// (1,0)• createPoint (w, 1, 2); // (1,2)

Page 38: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

38

Типи параметрів (перший підсумок)

1. const T

2. T

3. T&

4. const T&

Копіювання, незмінний формальний параметр, немає впливу на фактичний параметр

• Копіювання, змінний формальний параметр, немає впливу на фактичний параметр

Відсилка без копіювання, повний доступ до фактичного параметру (C++)

Стала відсилка без копіювання, фактичний параметр незмінний (C++)

Page 39: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

39

Порівняння типів параметрів

Найнадійніший параметр-результатT&

Параметри-значенняТочка зору користувача:

параметри T , const T і const T& не відрізняються з точки зору використання

Точка зору розробника:const T надійніший, бо не створює непорозумінь;

const T& найефективніший, оскільки не вимагає витрат на копіювання

Page 40: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

40

Сталий параметр

• //Greatest Common Divider• int gcd (const int m0, const int n0)• {• int m = m0, n = n0;• while (m != n)• if (m>n) m=m-n; else n=n-m;• // m == n• // Початкові значення не втрачено• assert((m0%m==0) && (n0%n==0) );• return m;• }

Page 41: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

41

Параметри-указники

5. T*

6. const T*

7. T* const

8. const T*const

Повний але непрямий доступ до фактичного параметру; передача масивів (T[]) (в стилі чистого С)Маловживаний тип параметру; доступ лише для читання: сталий фактичний параметр (vs const T&)Незмінний формальний параметр-указник, немає впливу на фактичний параметр-адресу (this в C++)Незмінний указник на сталий фактичний параметр

В усіх випадках 5-8 сам указник передається значенням

Page 42: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

42

Головна проблема параметра-указника

Як відрізнити масив від скалярного значення?Вихід: жорстка дисципліна програмування, додатковий параметр типу size_t з відповідним коментарем

void f (double * px, size_t size_of_px);

Page 43: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

43

Типова помилка в параметрі-указнику

// Думалось, що ця функція виділятиме пам’ять для// указника t• void allocate (char *t, size_t n, char c)• {• t = new char [n];• t[n-1]='\0';• for (int i=0;i<n-1;i++)• t[i]=c;• cout<<“This is inside: “<<t<<endl;• return;• }

Page 44: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

44

Результат

// Виклик функції allocate • char a[]=“This was before”;• cout<<a<<endl;// This was before• allocate (a, 10, ‘a’); // This is inside: aaaaaaaaaa• cout<<a<<endl;// This was before

// Вихід: передати указник відсилкою• void construct (WrappedVector &);

Page 45: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

45

Параметри-указники

9. T**

10.T*&

. . . . . . . . . . . . . . . . .11.const T* const * const

Указник-вихідний параметр (чистий С)

Те ж саме, але в стилі С++

А ще різні варіації на тему const

Page 46: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

46

Указник другого рівня

// Тепер правильно • void allocate (char **t size_t n, char c)• {• *t = new char [n];• (*t)[n-1]='\0';• for (int i=0;i<n-1;i++)• (*t)[i]=c;• cout<<*t<<endl;• return;• }

Page 47: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

47

Виклик указником другого рівня

// Виклик функції allocate • char *a=“This was before”;• cout<<a<<endl;// This was before• allocate (&a, 10, ‘a’); // This is inside: aaaaaaaaaa• cout<<a<<endl;// aaaaaaaaaa

Page 48: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

48

Псевдонім указника

• void allocate (char *&t, size_t n, char c)• {• t = new char [n];• t[n-1]='\0';• for (int i=0;i<n-1;i++)• t[i]=c;• cout<<t<<endl;• return;• }

Page 49: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

49

Виклик відсилкою до указника

// Виклик функції allocate • char *a=“This was before”;• cout<<a<<endl;// This was before• allocate (a, 10, ‘a’); // This is inside: aaaaaaaaaa• cout<<a<<endl;// aaaaaaaaaa

Page 50: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

50

Особливості нульового параметру-указника

Структура дерева

• struct Tree • {• int node;• Tree *left;• Tree *right;• };

Вузли-листя мають нульові указники left і right

Page 51: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

51

Вершина дерева

Параметр aTree відіграє роль параметру-результату

• void createTree(Tree **aTree, int node, Tree *left, Tree

*right)• {• *aTree = new Tree;• (*aTree) -> node = node;• (*aTree) -> left = left;• (*aTree) -> right = right;• return;• }

Page 52: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

52

Видалення дерева

• void destroyTree(Tree **aTree)• {• Tree *subTree;• if ((*aTree)==0) return;• subTree = (*aTree)->left; //left

subtree• destroyTree(&subTree);• subTree = (*aTree)->right; //right subtree• destroyTree(&subTree);• delete *aTree; //delete root• *aTree = 0;• return;• }

Page 53: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

53

Приклад використання

• int main()• {• Tree * t, *t1, *t2;• createTree(&t1,1,0,0);• createTree(&t2,2,0,0);• createTree(&t,3,t1,t2);• destroyTree (&t); //Проблема: значення t1 і

t2• return 0;• }

Page 54: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

54

Завданння

Переписати обробку дерев, замінивши скрізь, де можна указники відсилками

Page 55: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

55

Указники vs. відсилки

Замінимо• void createTree

(Tree **aTree, int node, Tree *left, Tree *right);на• void createTree

(Tree *&aTree, int node, Tree *left, Tree *right);але не• void createTree

(Tree *&aTree, int node, Tree &left, Tree &right);

бо виклик createTree(t1,1,0,0); стане незаконним

Page 56: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

56

Зведення типів при передачі параметрів

• void show (double x)• {• cout<<x<<endl;• }// OK• int k=1; show(k); //1

• long int lk=2; show(lk); //2

• float x=3; show(x); //3•

Page 57: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

57

Неявне зведення відсилок неможливе

• void show (double & x)• {• cout<<x<<endl;• }// ERRORS• int k=1; show(k);

• long int lk=2; show(lk);

• float x=3; show(x);

Page 58: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

58

Явне зведення відсилок хибне

• void show (double & x)• {• cout<<x<<endl;• }// Type conversion• int k=1; show((double&)k); //-9.25596e+061

• long int lk=2; show((double&) lk); //2.122e-314

• float x=3; show((double&) x); //4.77656e-314

• Не намагайтеся допомогти компілятору: не вийде!

Page 59: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

59

Неявне зведення указників неможливе теж

• void show (double * x)• {• cout<<x<<endl;• }// ERRORS• int k=1; show(&k);

• long int lk=2; show(&lk);

• float x=3; show(&x);

Page 60: 08 Functions

3. Обчислення результату

Page 61: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

61

Результат функції

Результати значення1. T f(…);2. const T f(…);

Результати відсилки3. T& f(…);4. const T& f(…);

Результати указники5. T* f(…):

Page 62: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

62

Результати-значення

Типи результатів T і const T не різняться для типів даних, прийнятих в С (далі в С++ будуть відрізнятися)

Page 63: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

63

Точка площини

• struct Point• { • double _x; double _y;• };• const Point plus(Point u, Point v)• { • Point res;• res._x = u._x+v._x;• res._y = u._y+v._y;• return res;• }

Page 64: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

64

Дерево

Як і в попередньому прикладі результат повністю копіюється при виході з функції

• Tree createTree ( int node, Tree * left, Tree * right)• {• Tree aTree;• aTree.node = node;• aTree.left = left;• aTree.right = right;• return aTree;• }

Page 65: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

65

Результати-відсилки

Дають повний доступ до частин агрегатів даних, але не забувайте про правильну передачу параметру

• double& x (Point u) • {• return u._x;• }

• Point v; v._x = 10; v._y = 20;• cout<<x(v) <<endl; //10• x(v)= 125;• cout<< x(v)<<endl; //10, а не 125 ?!

Page 66: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

66

Результати і параметри-відсилки

Тепер повний доступ до параметру

• double& x (Point & u) • {• return u._x;• }

• Point v; v._x = 10; v._y = 20;• cout<< x(v) <<endl; //10• x(v)= 125;• cout<< x(v) <<endl; // 125, а не 10?!

Page 67: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

67

Сталі відсилки

Результати не копіюються, але й не доступні для змін

• const double& x (const Point & u) • {• return u._x;• }

• Point v; v._x = 10; v._y = 20;• cout<< x(v) <<endl; //10• // x(v)= 125; not possible now

Page 68: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

68

Результати-указники

• Tree* createTree (int node, Tree *left, Tree *right)• {• Tree * aTree = new Tree;• aTree->node = node;• aTree->left = left;• aTree->right = right;• return aTree;• }Тепер можлива суперпозиція• t = createTree (3, createTree (1,0,0), createTree

(2,0,0));

Page 69: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

69

Висновки

• Результат, створений у тілі функції, передаємо значенням

• Доступ до частини або всього агрегату даних, переданого фактичним параметром, забезпечуємо результатом відсилкою

• Створені у функції агрегати даних передаються указником

Page 70: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

70

Рекурсія

Перетворює визначення в програму

• int gcd (int v1, int v2)• {• return v2 ? gcd (v2, v1%v2) : v1;• }

Page 71: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

71

Неефективність рекурсії

• int BadFib(int n)• {• // Так не варто рахувати!!!• if (n==0) return 0; • if (n==1) return 1; • return BadFib(n-1)+BadFib(n-2);• }

Page 72: 08 Functions

© Бублик В.В. Програмування-2. 8. Процедурне програмування. Функції

72

Ефективна рекурсія

• void fib (int &f1, int &f2, int n)• {• // n зменшується на 1, f1 і f2 зсуваються

вправо• int f;• if (n>=2)• {• f=f2; f2+=f1; f1=f;• fib(f1, f2, n-1);• }• }