2011-07-31 15 views
10

Mam wrażenie, że to pytanie jest wystarczająco podstawowe, aby gdzieś tam być, ale nie mogę znaleźć odpowiedzi na to pytanie.Deklaracja odniesienia do obiektu i operatora przypisania

Załóżmy, że mam tego kodu:

//class member function 
std::map< std::string, std::string > myMap; 

const std::map< std::string, std::string >& bar() 
{ 
    return myMap; 
} 

void myFunc(std::map< std::string, std::string >& foo1) 
{ 
    foo1 = bar(); 
    std::map< std::string, std::string >& foo2 = bar(); 
} 

Moje zrozumienie jest, że jeśli zacznę za pomocą foo2, ponieważ foo2 jest nawiązaniem do tej samej instancji jak to, co bar() zwraca, coś zrobić z foo2 będzie odzwierciedlone w myMap. Ale co z foo1? Czy foo1 otrzymuje kopię myMap, czy też wskazuje na to samo wystąpienie, co funkcja zwracana przez bar()? Biblioteka standardowa C++ mówi, że operator przypisania dla std :: map skopiuje elementy, ale czy to oznacza, że ​​operator przypisania nie jest tak naprawdę wywoływany w deklaracji foo2?

Dzięki!

Odpowiedz

15

Referencje nie można zmieniać w C++. Oznacza to, że po ich inicjalizacji nie można ich ponownie przypisać. Zamiast tego, każde zadanie rzeczywiście dotyczy obiektu, do którego się odnosi. Tak w kodzie,

foo1 = bar(); 
std::map< std::string, std::string >& foo2 = bar(); 

pierwsza linia nazywa std::map::operator= na obiekcie, który został przekazany jako parametr do myFunc. Po tym, foo1 fotosy odnosi się do tego samego obiektu - ale jego wartość (np. Jakie elementy posiada) może bardzo dobrze została zmieniona.

Pamiętaj, że druga linia to , a nie zadanie, jeśli kiedykolwiek pojawiły się wątpliwości. Zamiast tego jest inicjalizacją. Ponieważ typem zwracanego paska jest w rzeczywistości std::map<std::string, std::string> const&, nie można powiązać z std::map<std::string, std::string>&, więc jest to błąd kompilacji.


Aby rozwinąć stronę "filozoficzną", referencje w C++ są tak przejrzyste, jak to możliwe i tak naprawdę nie istnieją jako obiekty. Jest to przy użyciu standardowego znaczenia C++ tego terminu (nie jest ono powiązane z OOP): oznacza to, że na przykład typy odniesienia mają rozmiar , a nie. Zamiast tego, sizeof(T&) == sizeof(T). Podobnie odwołania nie mają adresów i nie można utworzyć wskaźnika lub odniesienia do odwołania: dany int& ref = i;, a następnie &ref == &i.

Odniesienia są zatem celowo przeznaczone do użycia tak, jakby używane obiekty były używane. Jedyną rzeczą charakterystyczną dla odniesienia, która ma miejsce w czasie życia referencji, jest jej inicjalizacja: do czego może się wiązać i co to znaczy w sensie życia.

+0

+1 Dziękuję, sam nauczyłem się czegoś nowego. Właśnie zrobiłem test i naprawdę byłem absolutnie w 100% NIEPRAWIDŁOWY i masz rację = -) – flumpb

+0

Dobrze! Dzięki, naprawdę musiałem wiedzieć, że operator przypisania jest wywoływany w foo1 i nie jest wywoływany w foo2. Świetne wyjaśnienie, dzięki! – bhh1988

+0

@Luc Jeśli to możliwe, czy możesz wyjaśnić, dlaczego zwykle nie używasz zmiennych referencyjnych?Mam lepsze zrozumienie tego, czym one są (dzięki twojej odpowiedzi), ale wygląda na to, że koderowie zazwyczaj faworyzują wskaźniki. Czy to jest redundancja? Ograniczony zakres? –

0

Linia

foo1 = bar(); 

tworzy kopię (bo to co robi operator przypisania map „s).

+0

wydaje się dziwne, aby zwrócić odniesienie do zmiennej globalnej, nie? –

+0

@ 0A0D: Nie bardzo, może być użyty do enkapsulacji, jeśli zmienna "globalna" nie ma w rzeczywistości powiązania zewnętrznego. Lub możesz zwrócić referencję do zmiennej globalnej "a" lub zmiennej globalnej "b". –

Powiązane problemy