2009-04-14 12 views

Odpowiedz

20

Wersja & oznacza odniesienie natomiast * wersja reprezentuje wskaźnik. Różnica jest zbyt duża dla typowego postu SO. Proponuję zacząć od C++ FAQ Lite

http://www.parashift.com/c++-faq-lite/references.html

I zazwyczaj nie lubią odpowiadać posty z „należy użyć google” odpowiedź. Jednak jest to jeden temat, który bardzo polecam Ci google. W szczególności google "wskaźniki C++ vs. referencje". Na ten temat dostępnych jest wiele informacji, a dyskusje na tych stronach przeważają nad wszystkim, co tutaj napiszemy.

+1

Myślę, że Joel i Jeff byliby zadowoleni jako cios, gdyby ktokolwiek wykorzystujący Google do udzielenia odpowiedzi na to pytanie został skierowany na stronę StackOverflow i pod wrażeniem reklamodawcy StackOverflow. –

+3

Tak, wiem, że to jest stare. Ale wylądowałem na tej stronie po wyszukiwarce Google dla "różnicy między referencją a wskaźnikiem". Był to wynik # 3. – Ross

+2

ugh, ja googliłem i przyszedłem tutaj ... Dosłownie to samo pytanie, które mam. –

5

Klasa * może wskazywać na obiekt klasy dowolny obiekt klasy lub nie mieć go wcale.

Klasa zawsze wskazuje na obiekt klasy dokładnie jeden obiekt klasy i nigdy nie może wskazać innego obiektu.

Ponadto uważam, Bjarne jest członkiem zbiór ludzi, którzy twierdzili, „tablice w C są podzielone nie do naprawienia” klasy * może wskazywać na zupełnie ding-Dang tablicy obiektów klasy, w kolejce jeden po drugim w pamięci, aw C nie ma absolutnie żadnej możliwości określenia, czy klasa * wskazuje na jedną czy wiele osób.

6

* jest wskaźnikiem, odniesienie to &. Różnica między nimi polega na tym, że wskaźnik jest obszarem pamięci, który musi zostać dereferencjonowany, np. za pomocą operatora ->, aby być "widzianym" jako instancja klasy. Odniesieniem jest zamiast tego "alias", po prostu alternatywna nazwa dla tej samej instancji klasy. Nie musisz używać operatora -> z referencją. Używasz operatora kropki.

Osobiście rzadko używałem referencji, głównie gdy miałem obiekt wartości, który przydzieliłem na stosie. Nowy operator zawsze zwraca wskaźnik, który następnie musisz wyłuskać. Ponadto jedną z najbardziej problematycznych kwestii odniesień jest to, że nie można ich ustawić na NULL. W niektórych przypadkach przydatne jest posiadanie funkcji, która akceptuje wskaźnik obiektu lub NULL. Jeśli twoja funkcja akceptuje referencję, nie możesz przekazać wartości NULL (można jednak użyć wzorca obiektu Null).

+0

Oczywiście, wskaźniki zerowe są ogromnym źródłem błędów w C++, więc nie sądzę, że referencje są złe pod tym względem. –

0

Kolejna różnica polega na tym, że zmienne referencyjne muszą zostać zainicjowane. Nie można utworzyć zmiennej referencyjnej, takiej jak pokazana w przykładowym kodzie. To spowodowałoby błąd kompilatora.

0

Odwołanie (&) jest takie samo jak wskaźnik (*), z tym że kompilator C++ zapewnia, że ​​nie ma on wartości NULL. Jednak nadal może to być zwisający wskaźnik (zmienna wskaźnika, która nie ma odnośnika, tak że jest śmieciowa i nieważna dla dowolnego użycia).

0

Jak stwierdzono należy go google, ale żeby uniknąć nieporozumień:

  • Referencje nie są zmiennymi
  • Referencje nie są podobne do wskaźników (ale można ich używać w podobny sposób)

Pomyśl o odwołaniu jako skrócie do terminu, który jest do niego przypisany.

0

Jedna dodatkowa wskazówka, że ​​chciałbym zaproponować jest następująca:

używać odwołań, kiedy można, wskaźniki, kiedy trzeba. Jeśli obiekt jest gwarantowany, prawdopodobnie powinieneś użyć referencji. Jeśli nie jest, to prawdopodobnie musisz użyć wskaźnika.

Dodatkową zaletą jest to, że referencje usuwają niejednoznaczność dotyczącą własności. Gdy programista zajmie się wskaźnikiem, zaczną zastanawiać się, czy powinni go usunąć.

Sprawdź ten przykład z:

 
// Wrapper class using a reference because the wrapped object always exists 
class Wrapper 
{ 
public: 
    // If the wrapped is guaranteed to exist at creation, do it this way 
    Wrapper(Wrapped& wrapped):_wrapped(wrapped) { /* empty */ } 

    // put extra methods here. 
    int getWrappedValue() const { return _wrapped.getValue(); } 

private: 
    Wrapped& _wrapped; // This object always exists and is valid 
}; 

// Wrapper class written to support a possibly non-existent wrapped object. 
class Wrapper 
{ 
public: 
    Wrapper(Wrapped* wrapped = 0):_wrapped(wrapped) { /* empty */ 

    void setWrappee(WRappee* wrapped) { _wrapped = wrapped; } 

    int getWrappedValue() const; // Not making inline -- more complex 

private: 
    Wrapped* _wrapped; // Always check pointer before use 
}; 

int Wrapper::getWrappedValue() const 
{ 
    if (_wrapped) 
    { 
    return _wrapped->getValue(); 
    } 
    else 
    { 
    return -1; // NOTE, this is a contrived example -- not getting into exceptions 
    } 
} 
Powiązane problemy