Tworzenie kodu źródłowego w oparciu o funkcje jest praktyczne - właściwe stosowanie funkcji wpływa bowiem pozytywnie na organizację kodu pisanej aplikacji. Dobrze zorganizowany kod zapewnia przejrzystość, a co za tym idzie efektywność pracy. Skoro korzystne jest wydzielanie kodu do funkcji to warto poznać lepiej możliwości pracy z funkcjami jakie daje nam język C++. W niniejszym rozdziale skoncentrujemy się na przekazywaniu argumentów do funkcji przez tzw.
referencję. Zanim jednak dojdziemy do zagadnienia
referencji postaram się najpierw zwiększyć Twoją świadomość w zakresie tego czego do tej pory używaliśmy :)
Argumenty funkcji - zmienne lokalne
Zacznijmy tym razem od krótkiego kodu:
#include <iostream>
void wypisz( int iLiczba )
{
std::cout << "Wartosc liczby wynosi: " << iLiczba << std::endl;
iLiczba += 10;
std::cout << "Wartosc liczby wynosi: " << iLiczba << std::endl;
}
int main()
{
int iNaszaLiczba = 7;
std::cout << "Nasza liczba = " << iNaszaLiczba << std::endl;
wypisz( iNaszaLiczba );
std::cout << "Nasza liczba = " << iNaszaLiczba << std::endl;
return 0;
}
Standardowe wyjście powyższego programu będzie następujące:
Nasza liczba = 7
Wartosc liczby wynosi: 7
Wartosc liczby wynosi: 17
Nasza liczba = 7
Powyższy kod programu powinien być dla Ciebie zrozumiały bowiem opiera się o materiał, który został już omówiony w jednym ze wcześniejszych rozdziałów. Warto jednak w tym miejscu uwypuklić co się faktycznie dzieje ze zmienną o nazwie
iNaszaLiczba by w dalszej części rozdziału można było powiedzieć: "O, jakie to proste!".
No to zaczynamy! Pierwsza linijka
int iNaszaLiczba = 7;
, czyli zainicjalizowanie zmiennej
iNaszaLiczba wartością
7 - banał :) Druga i czwarta linijka w funkcji głównej programu jest również banalna, tj. wypisuje aktualną wartość zmiennej
iNaszaLiczba:
std::cout << "Nasza liczba = " << iNaszaLiczba << std::endl;
Cała magia jest zawarta w linijce trzeciej tj.
wypisz( iNaszaLiczba );
i właśnie tej linijce poświęcimy teraz całą naszą uwagę. Wartość, którą przekażemy do argumentu funkcji
wypisz zostanie
skopiowana. Oznacza to, że wewnątrz funkcji argument
int iLiczba jest nową zmienną, której nadano po prostu taką samą wartość jaką posiadała zmienna
iNaszaLiczba. Przekładając to na pismo obrazkowe, sytuacja wygląda następująco:
Argumenty funkcji - referencje
Kopiowanie danych przekazywanych do funkcji bardzo często nie jest pożądanym efektem - dane przekazywane do funkcji mogą zajmować bowiem dużo miejsca w pamięci i wówczas niepotrzebnie będziemy tracili moc obliczeniową komputera na tworzenie ich kopii. Aby zapobiec kopiowaniu danych wystarczy użyć symbolu
&
w odpowiednim miejscu argumentu. W którym to miejscu? O tym poniżej :)
Referencja - zapis formalny
Referencja w C++ jak już wcześniej wspomniałem oznaczona jest przez symbol
&
. Symbol ten umieszcza się za typem zmiennej i jednocześnie przed podaniem jej nazwy. Przekładając te słowa na język C++ będzie to wyglądało tak:
int & zmienna
.
Opisana powyżej zasada jest regułą ogólną i dotyczy nie tylko argumentów funkcji ale również zwykłych zmiennych. Zagadnienia związane z referencją zmiennych zostaną jednak omówione dużo później - teraz skupimy się tylko i wyłącznie na referencjach w argumentach funkcji.
Referencja w argumentach funkcji
Skoro znamy już regułę zapisu zmiennych w postaci referencji zobaczmy gwoli formalności jak będzie wyglądał zapis argumentu funkcji używający referencję:
void funkcja( typ_argumentu & nazwa_argumentu )
Jak widać żadnej większej filozofii w zapisie nie ma :) Dane przekazane poprzez argument funkcji używający referencję nie będą kopiowane. W konsekwencji będziemy pracowali na oryginalnych danych co w praktyce oznacza, że modyfikacja wartości zmiennej zmodyfikuje nam zmienną tą, która została przekazana do funkcji poprzez argument.
Argument funkcji jako referencja - podsumowanie
Podsumowaniem całych wywodów związanych z referencją postanowiłem ująć w postaci prostego schematu, który powinieneś dodatkowo przeanalizować w celu lepszego utrwalenia wiedzy z niniejszego materiału. Oto on:
Przykłady
Program pierwszy
#include <iostream>
void wypisz( int & iLiczba )
{
std::cout << "Wartosc liczby wynosi: " << iLiczba << std::endl;
iLiczba += 10;
std::cout << "Wartosc liczby wynosi: " << iLiczba << std::endl;
}
int main()
{
int iNaszaLiczba = 7;
std::cout << "Nasza liczba = " << iNaszaLiczba << std::endl;
wypisz( iNaszaLiczba );
std::cout << "Nasza liczba = " << iNaszaLiczba << std::endl;
return 0;
}
Standardowe wyjście programu:
Nasza liczba = 7
Wartosc liczby wynosi: 7
Wartosc liczby wynosi: 17
Nasza liczba = 17
Program drugi
#include <iostream>
#include <limits>
bool wczytaj_liczbe( int & liczba )
{
std::cin >> liczba;
if( std::cin.fail() )
{
std::cin.clear();
std::cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' );
return false;
}
return true;
}
int main()
{
int x;
do
{
std::cout << "Podaj liczbe: ";
} while( wczytaj_liczbe( x ) == false );
std::cout << "Liczba podana to: " << x << std::endl;
return 0;
}
Przykładowe standardowe wyjście programu:
Podaj liczbe: abc
Podaj liczbe: nie dziala
Podaj liczbe: 123
Liczba podana to: 123
Zadanie domowe
Przeanalizuj działanie wszystkich programów, które wystąpiły w niniejszym rozdziale. Poeksperymentuj z nimi dodając i zabierając symbol referencji w argumentach funkcji. Napisz dowolny program wykorzystujący referencję w argumentach funkcji.