Скачать презентацию
Идет загрузка презентации. Пожалуйста, подождите
Презентация была опубликована 9 лет назад пользователемНина Новицкая
1 Лекції для студентів 2 курсу Консультації: вівторок, середа, четвер год., кімн. 204/1, к афедра мультимедійних систем Cologn Бублик Володимир Васильович Процедурне програмування C/C++ Лекція 9. Передача параметрів
2 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 2 (57) Виклик функції Розглянемо оголошення функції void f (T x); де f ім'я функції, T тип параметру, x ім'я параметру Розглянемо виклик цієї функції f(e); де e вираз підходящого типу (фактичний параметр) Виконання функції починається визначенням локальної змінної для параметру x з її одночасною ініціалізацією T x = e;
3 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 3 (57) Передача параметрів значенням Ініціалізація T x = e; говорить про те, що перед виконанням функції обчислюється значення фактичного параметру е (r- value) Кажуть, що параметри передаються значенням Залежно від типу T ці значення можуть бути 1.значеннями базових типів, структур, 2.адресами (у випадку указників) 3.відсилками (у випадку псевдонімів)
4 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 4 (57) Сторонній ефект 1.Якщо передаються значення базових типів або структур, то виконання функції не впливає на наступні значення фактичних параметрів 2.Якщо формальний параметр є указником, то можлива зміна значення елементу пам'яті, на який цей указник встановлено 3.Якщо формальний параметр псевдонім, то через нього функція одержує прямий доступ до елементу пам'яті, до якого псевдонім відсилає Якби не було стороннього ефекту, то який сенс мали б функції виду void f (T x)?
5
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 5 (57) Приклад 1. swap void swap( double x, double y) {// значення базового типу double double z = x; x=y; y=z; cout<
6
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 6 (57) Приклад 2. pswap void pswap(double *x, double *y) { double z = *x; *x=*y; *y=z; cout<<*x<<,<<*y<
7
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 7 (57) Приклад 3. rswap (тільки С++) void rswap( double &x, double &y) { double z = x; x=y; y=z; cout<
8
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 8 (57) Безпечність виклику Безпечні 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<
9 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 9 (57) Задача додому Що б це значило? Організуйте виклик функції ptrswap та графічно зобразіть роботу з пам'яттю void ptrswap( int *&u, int *&v ) { int *w = v; v = u; u = w; }
10 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 10 (57) Масиви як параметри Масиви головна причина використання параметрів- указників Використання параметром масиву нічим не відрізняється від параметра-указника T *a T a[]
11 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 11 (57)11 Приклад 4. Не має значення, як визначити один і той же параметр в кожній з трьох сигнатур void init (int* ch); void show (int ch[]); void swapar (int []); В усіх трьох прикладах передача параметра невдала, бо незрозуміло, скільки елементів у масиві
12 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 12 (57) Приклад 4 (1). const int n=26; int main() { int ch[n]; init (ch); show(ch); swapar(ch); show(ch); return 0; }
13 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 13 (57) Приклад 4(2). void init(int* ch) { for(int i= 'a'; i<'a'+n; ++i) //не дуже добре ch[i-'a'] = i; } Ніхто не заборонить навіть таке for(int i= 'a'; i<'a' ; ++i) ch[i-'a'] = i; Результат передбачити неможливо, швидше всього access violation
14 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 14 (57) Приклад 4(3). Допустимий навіть зовсім безглуздий виклик int ch; init(&ch); Теж access violation
15 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 15 (57) Приклад 4(1). Краще рішення передати розмір масиву додатковим параметром void init (int* ch, int n); void show (int ch[], int n); void swapar (int [], int);
16 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 16 (57) Приклад 4(2). int main() { // Розмір масиву визначено const int n=26; int ch[n]; init (ch, n); show (ch, n); swapar (ch, n); show (ch, n); return 0; }
17 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 17 (57) Приклад 4(2). void init (int* ch, size_t n) { for(int i= 'a'; i<'a'+n; i++) //тепер в порядку ch[i-'a'] = i; }
18
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 18 (57) Приклад 4(3). void show(int ch[n], size_t n) { cout<<"start string:"<
19
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 19 (57) Приклад 4(4). void swapar(int ch[], size_t n) { for (int i = 0; i
20 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 20 (57) Приклад 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
21 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 21 (57) Висновок Передаючи в функцію параметром масив (або указник як масив), передбачаємо розмір масиву додатковим параметром void f (T *array, size_t size); або краще void f (T [] array, size_t size);
22 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 22 (57) Загорнуті масиви //Визначення загорнутого вектора struct WrappedVector { static const int n;//статичне поле одне на всіх double * x; }; //сигнатура добутку (дуже погана) double prod (WrappedVector, WrappedVector);
23 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 23 (57) Параметри сталі відсилки //сигнатура добутку (краще) //структури не копіюються double prod (WrappedVector&, WrappedVector&); //сигнатура добутку (ще краще) //структури не копіюються, //доступ для зміни фактичного //параметру закрито double prod (const WrappedVector&, const WrappedVector&);
24
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 24 (57) Скалярний добуток //визначення статичного поля структури const int WrappedVector::n = 100; //визначення скалярного добутку double prod (const WrappedVector& a, const WrappedVector& b) { double s = 0; for (int i=0; i
25
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 25 (57) Створення вектору конструктор //Відсилка повний доступ void construct (WrappedVector &); void construct (WrappedVector & a) { a.x = new double [a.n]; for (int i=0; i
26 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 26 (57) Видалення об'єкту деструктор void destroy (WrappedVector& a) { delete [] a.x; a.x = 0; return; } //Як примусити кожного прибирати за собою?
27 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 27 (57) Типи параметрів (перший підсумок) 1.const T 2.T 3.T& 4.const T& Копіювання, незмінний формальний параметр, немає впливу на фактичний параметр Копіювання, змінний формальний параметр, немає впливу на фактичний параметр Відсилка без копіювання, повний доступ до фактичного параметру (C++) Стала відсилка без копіювання, фактичний параметр незмінний (C++)
28 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 28 (57) Порівняння типів параметрів Найнадійніший параметр-результат T& Параметри-значення Точка зору користувача: параметри T, const T і const T& не відрізняються з точки зору використання Точка зору розробника: const T надійніший, бо не створює непорозумінь; const T& найефективніший, оскільки не вимагає витрат на копіювання
29 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 29 (57) Параметри-указники 5.T* 6.const T* 7.T* const 8.const T*const Повний але непрямий доступ до фактичного параметру; передача масивів (T[]) (в стилі чистого С) Маловживаний тип параметру; доступ лише для читання: сталий фактичний параметр (vs const T&) Незмінний формальний параметр- указник, немає впливу на фактичний параметр-адресу (this в C++) Незмінний указник на сталий фактичний параметр В усіх випадках 5-8 сам указник передається значенням
30 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 30 (57) Головна проблема параметра-указника Як відрізнити масив від скалярного значення? Вихід: жорстка дисципліна програмування, додатковий параметр типу size_t з відповідним коментарем void f (double * px, size_t size_of_px);
31
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 31 (57) Типова помилка в параметрі-указнику //Думалось, що ця функція виділятиме память для //указника t void allocate (char *t, size_t n, char c) { t = new char [n]; t[n-1]='\0'; for (int i=0;i
32 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 32 (57) Результат //Виклик функції allocate char a[]=This was before; cout<
33 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 33 (57) Параметри-указники 9.T** 10.T*& const T* const * const Указник-вихідний параметр (чистий С) Те ж саме, але в стилі С++ А ще різні варіації на тему const
34
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 34 (57) Указник другого рівня //Тепер правильно void allocate (char **t size_t n, char c) { *t = new char [n]; (*t)[n-1]='\0'; for (int i=0;i
35 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 35 (57) Виклик указником другого рівня //Виклик функції allocate char *a=This was before; cout<
36
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 36 (57)© Бублик В.В. Програмування Процедурне програмування. Функції Псевдонім указника void allocate (char *&t, size_t n, char c) { t = new char [n]; t[n-1]='\0'; for (int i=0;i
37 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 37 (57) Виклик відсилкою до указника //Виклик функції allocate char *a=This was before; cout<
38 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 38 (57) Особливості нульового параметру-указника Структура дерева struct Tree { int node; Tree *left; Tree *right; }; Вузли-листя мають нульові указники left і right
39 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 39 (57) Вершина дерева Параметр aTree відіграє роль параметру-результату void createTree (Tree **aTree, int node, Tree *left, Tree *right) { *aTree = new Tree; (*aTree) -> node = node; (*aTree) -> left = left; (*aTree) -> right = right; return; }
40 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 40 (57) Видалення дерева 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; }
41 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 41 (57) Приклад використання 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; }
42 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 42 (57) Завданння Переписати обробку дерев, замінивши скрізь, де можна указники відсилками
43 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 43 (57) Указники 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); стане незаконним
44
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 44 (57) Зведення типів при передачі параметрів void show (double x) { cout<
45
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 45 (57) Неявне зведення відсилок неможливе void show (double & x) { cout<
46
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 46 (57) Явне зведення відсилок хибне void show (double & x) { cout<
47
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 47 (57) Неявне зведення указників неможливе теж void show (double * x) { cout<
48 Повернення результату Результат функції може бути значенням, сталим значенням, відсилкою, сталою відсилкою або указником
49 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 49 (57) Результат функції Результати значення 1.T f(…); 2.const T f(…); Результати відсилки 3.T& f(…); 4.const T& f(…); Результати указники 5.T* f(…):
50 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 50 (57) Результати-значення Типи результатів T і const T не різняться для типів даних, прийнятих в С (далі в С++ будуть відрізнятися)
51 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 51 (57) Точка площини 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; }
52 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 52 (57) Дерево Як і в попередньому прикладі результат повністю копіюється при виході з функції Tree createTree ( int node, Tree * left, Tree * right) { Tree aTree; aTree.node = node; aTree.left = left; aTree.right = right; return aTree; }
53
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 53 (57) Результати-відсилки Дають повний доступ до частин агрегатів даних, але не забувайте про правильну передачу параметру double& x (Point u) { return u._x; } Point v; v._x = 10; v._y = 20; cout<
54
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 54 (57) Результати і параметри-відсилки Тепер повний доступ до параметру double& x (Point & u) { return u._x; } Point v; v._x = 10; v._y = 20; cout<< x(v) <
55
© 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 55 (57) Сталі відсилки Результати не копіюються, але й не доступні для змін const double& x (const Point & u) { return u._x; } Point v; v._x = 10; v._y = 20; cout<< x(v) <
56 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 56 (57) Результати-указники 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));
57 © 2006 Бублик В.В. Процедурне програмування. 9. Передача параметрів 57 (57) Висновки Результат, створений у тілі функції, передаємо значенням Доступ до частини або всього агрегату даних, переданого фактичним параметром, забезпечуємо результатом відсилкою Створені у функції агрегати даних передаються указником
Еще похожие презентации в нашем архиве:
© 2024 MyShared Inc.
All rights reserved.