В наших предыдущих статьях, мы уже упоминали о том, що параметри можна передавати у функцію по значению или по указателю. Так работали при написании программ на языке C. В C появляется возможность передавать параметры в функции по ссылке. Рассмотрев пример из этого урока, вы заметите, что применять ссылки удобнее чем указатели.
Ссылка – это альтернативное имя переменной (её псевдоним, иными словами). Когда функция принимает параметр по ссылке, имя параметра становится псевдонимом переменной, которую мы передаём в функцию. Такой метод передачи данных позволяет функции работать со значениями переменных, которые передаются в неё, а не с копиями этих переменных.
Определяя функцию, чтобы указать, что параметр является ссылкой, необхідно перед його ім'ям додати амперсанд &.
Набирайте следующий пример и всё должно стать понятным:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #include <iostream> using namespace std; void showVariables(int varInt, double varDbl); void change(int varInt, double varDbl); // передача по значению void changeRef(int& varInt, double& varDbl); // передача по ссылке void changePtr(int* varInt, double* varDbl); // передача по указателю int main() { setlocale(LC_ALL, "rus"); int varInteger = 0; double varDouble = 0.0; cout << "Передаем параметры по значению!" << endl; change(varInteger, varDouble); showVariables(varInteger, varDouble); cout << "Передаем параметры по ссылке!" << endl; changeRef(varInteger, varDouble); // передаем, как обычную переменную showVariables(varInteger, varDouble); cout << "Передаем параметры по указателю!" << endl; changePtr(&varInteger, &varDouble); // используем амперсанд, чтобы передать адрес showVariables(varInteger, varDouble); return 0; } void showVariables(int varInt, double varDbl) { cout << "Значения переменных после изменений:\n"; cout << "Первая переменная (int) = " << varInt << endl; cout << "Вторая переменная (double) = " << varDbl << endl; cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n"; } //================================================================ void change(int varInt, double varDbl) { varInt = 100; varDbl = 111.11;; } //================================================================ void changeRef(int& varInt, double& varDbl) { varInt = 200; // обращаемся, как к обычной переменной varDbl = 222.22; } //================================================================ void changePtr(int* varInt, double* varDbl) { *varInt = 300; // применяем разыменование *varDbl = 333.33; } |
Почнемо з функціїchange(). Вызвав ее в строке 17 исходного кода, передаем в неё переменные по значению. Функция благополучно создаст копии этих переменных, запише в них дані і, завершая свою “нелегкую” работу, уничтожит эти копии. В итоге никаких изменений с передаваемыми переменными не произойдёт.
Теперь посмотрите на определение функции changeRef(), в которую параметры передаются по ссылке – строки 45 – 49. Как говорилось выше, мы использовали & , чтобы сообщить компилятору о том, что принимаемые параметры – это ссылки. Усередині самої функції ми звертаємося до посилань, как к обычным переменным. То есть нам не надо применять операцию разыменования, если надо изменить значение переменной:
А викликаючи цю функцію з головною (рядок 21), нам не треба, при передаче переменных, применять операцию взятия адреса (тот же & , но с другим подтекстом), как это необходимо делать при передаче по указателю. Результат работы функции увидим, отобразив значение переменных на экран. Значения переменных успешно изменены.
Напоследок – передача по указателю. Сразу к определению changePtr() – строки 51 – 55. Тут есть то, чего мы не использовали при передаче по ссылке – разыменование указателей для изменения значений переменных:
Так як функція повинна прийняти змінні за вказівником, а указатель хранит адрес, то при вызове (рядок 25) передаём в неё адреса переменных:
Результат работы программы:
Мені не зовсім хочеться навантажувати вас якийсь додатковою інформацією про посилання. Они чаще всего применяются именно для передачи параметров в функцию. В роли параметров могут выступать переменные, массивы (это нам знакомо). Но что более важно – по ссылке в функцию передаются объекты структур и классов. Придет время и мы поговорим об этом.
Єдине, что касается синтаксиса, если вам понадобится объявить ссылку в программе, то ее необходимо сразу инициализировать (показать для какой переменной она создана). Наприклад:
Так в программе мы можем использовать имя ссылки для последующего обращения к данным, которые хранит aaa. Это если например кто-то до вас написал код и дал название переменной aaa. Этот программист знает, що вона зберігає кількість ящиків. А вы, для своєї зручності, дали этой переменной псевдоним amountOfBoxesи используете это новое имя, дописуючи якийсь новий код в програму.
Предлагаю посмотреть видео о параметрах функций, где в том числе рассказано и о ссылках.
Ссылка – это альтернативное имя переменной, ІМХО більше тут пояснювати нічого. Мінлива одна, імен кілька. По любому імені зі змінною можна як завгодно працювати. У разі з посиланнями в аргументах функцій теж саме, просто альтернативне ім'я змінної буде видно всередині функції.
Ну і пару прикладів я б додав.
т.к. указатель – це теж змінна (просто зберігає адресу об'єкта), то в функцію можна передавати посилання на покажчик наприклад
недійсними Foo(int &*arr);
Ну типу того.
І ще приклад, есть 2 функции:
недійсними Foo(INT * а);
недійсним бар(int &a);
Перша приймає посилання на об'єкт, друга- указатель.
Десь в програмі (наприклад у функції main є об'єкт:
INT був = 123;
Якщо треба передати його в першу функцію – то ми повинні отримати адресу об'єкта:
Foo(&var);
у другу – можна просто передавати, при цьому всередині функції буде використовувати альтернативне ім'я об'єкта
бар(var);
Якщо нам треба буде визначити покажчик на об'єкт – то він теж повинен инициализироваться адресою:
INT * р = &var;
Всередині першої функції з об'єктом працюють як зазвичай (адже у нас просто є альтернативне ім'я):
недійсними Foo(int &a) { a = 456; }
У другій функції ми маємо покажчик, тому змушені разименовивать його для звернення до об'єкту:
недійсним бар(INT * а) { *a = 789; }
// якщо a – указатель,
// те (*a) – об'єкт,
// і (&(*a)) – адреса об'єкта дужках можна прибрати, поставив для ясності (вони відображають пріоритети).
переплутані назви.
“І ще приклад, есть 2 функции:
недійсними Foo(INT * а);
недійсним бар(int &a);
Перша приймає посилання на об'єкт, друга- покажчик.”
навпаки!
посилання – досить неприємне для початківців поняття в C ++ (хоча цілком природне навіть для початківців в Java або Python).
Для початківців можна сказати так (хоча це і не зовсім точо):
– посилання на змінну – це в точності те ж, що і покажчик на неї, але до цим посиланням, на відміну від покажчика, не можна застосовувати адресну арифметику (+, -, ++, –).
Це неточно за змістом, але відразу дозволяє використовувати посилання в своєму коді без помилок.
Олег, відмінно що Ви приділяєте увагу нашим статтям і робите важливі замітки до викладеного матеріалу. Спасибі і від адміна сайту і, думаю, від відвідувачів )
Жоден початківець тебе не розуміє. Твої пояснення зовсім незрозумілі, наступна статися твоя і зрозуміти її дуже складно, неможливо. А ось ця стаття дуже легка до сприйняття. Не треба більше статей як Покажчики на функції
Що значить “жоден”? Не розуміють тільки самі тупі ;-) … інші хоч щось, да розуміють.
Програмування – це взагалі дуже не просте інженерна дисципліна, і пояснювати її “на пальці” неможливо і шкідливо так само, як, например, матаналіз або накреслювальну геометрію.
І освоїти програмування зможуть тільки ті, хто будуть багато і наполегливо практикуватися і самостоятельно писати код.
P.S. А від навчання на рівні пояснень “двічі два, дітки, виходить іноді чотири, якщо ви не проти” – ніхто і нічому не навчиться, виникне тільки ілюзія що “я теж чогось там вчився”.