Dobra, czym się różni przekazywanie przez referencję od przekazywania przez wskaźnik. Na pierwszy rzut oka niczym. Przy okazji rozwieję Twoje pierwsze wątpliwości o przekazywaniu przez wskaźnik. Niczego nie musisz definiować:
void foo1(int & a)
{
a = 5;
}
void foo2(int * a)
{
*a = 5
}
void bar()
{
int x = 0;
foo1(x);
int y = 0;
foo2(&y);
}
W tym przykładzie zarówno x jak i y będą miały na koniec wartość 5. Zobacz, jak przekazałem y do funkcji foo2. Nie deklarowałem żadnego wskaźnika.
W tym przypadku nie ma żadnej różnicy w działaniu. W nowoczesnym programowaniu zaleca się stosowanie referencji zamiast wskaźników, bo są bardziej czytelne. No i jakieś takie bardziej przyjazne. Ale są sytuacje, w których nie da się bez wskaźnika.
Załóżmy taki przykład, że masz jakąś klasę. Nazwijmy ją Connector. Nie jest ważne, co robi. Ale ważne jest to, że obiektu tej klasy nie możesz tworzyć sam. Musi być utworzony przez jakąś inną, prawdopodobnie zewnętrzną funkcję. Teraz taka funkcja może mieć dwojaką postać, np:
Connector * CreateConnector()
{
return new Connector();
}
//albo np:
bool CreateConnector(Connector *& pObj)
{
try
{
pObj = new Connector();
return true;
}catch(...)
{
return false;
}
}
Coś się tu może nie skompilować, bo pisałem na sucho. Pierwszy przykład wiadomo jak działa, nie ma co omawiać. W drugim przykładzie musisz przekazać wskaźnik do referencji. Czasami robi się wskaźnik na wskaźnik: (Connector ** ppConnector).
Różnica w wywołaniu jest taka:
Connector *pC1 = CreateConnector();
Connector * pC2;
if(CreateConnector(pC2))
{
//
}
Generalnie zawsze stosuj referencje, chyba że naprawdę musisz mieć wskaźnik z jakiegoś powodu.
Co do tablic. Przede wszystkim nie stosuj tablic. Staraj się ich unikać. Zamiast nich, stosuj odpowiedni kontener z STL, np. vector.
Ale, żeby dopełnić tematu.
Nie ma tak naprawdę różnicy, czy przekażesz tablicę przez wskaźnik, czy przez []. Tzn. w pierwszym przypadku przekażesz po prostu wskaźnik. W drugim przekażesz referencję do tablicy. W C++ z tego, co pamiętam, nie można przekazać tablicy przez wartość.
Oczywiście inaczej odnosisz się do tablicy przekazywanej przez wskaźnik, np:
void foo(int * pTab, int size)
{
int * pItem = pTab;
//dalej możesz sobie już patrzeć na kolejne elementy tablicy, po prostu inkrementując wskaźnik:
++pItem;
}
Ale uwaga! Tu jest niebezpieczeństwo. Jeśli będziesz posługiwał się wskaźnikiem pTab, np:
pTab++
to wtedy popsujesz sobie całą tablicę. Bo Twój wskaźnik na tablicę nie będzie już wskazywał na jej pierwszy element, tylko kolejny. Prosta droga do problemów z pamięcią i wycieków.</del>