2011-12-22 10 views
7

Zważywszy na przykład:Implikacje użycia znaku ampersand przed nazwą funkcji w C++?

inline string &GetLabel() { 
     return m_Label; 
}; 

Gdzie m_Label jest zmienną członek klasy prywatnego.

Sposób w jaki go rozumiem, funkcja zwraca referencję do zmiennej m_Label. Jakie byłyby konsekwencje używania tego w moim programie i czy byłoby lepiej po prostu zwrócić wartość, zamiast odniesienia? Dziękuję Ci!

Odpowiedz

6

Zwraca odniesienie do prywatnego członka.

Istnieje wiele przypadków, w których jest to pożądane, ale należy zachować ostrożność.

IMO generalnie nie jest dobrym pomysłem zwracanie kopii obiektu wewnętrznego, który nie jest typem integralnym, z uwagi na ogólną wydajność. Tak, wiem, że przedwczesna optymalizacja nie jest dobra, ale to nie jest tak naprawdę optymalizacja, to tylko dobra praktyka wydajnościowa, która pozwala dzwoniącemu określić wpływ na wydajność; jeśli chce kopii, może po prostu nie zadeklarować zmiennej, do której przypisuje ją jako odniesienie.

Istnieją 2 Ogólne zasady kciuka używam tutaj:

1) Jeżeli nie chcesz, aby rozmówca mógł zmodyfikować prywatny obiekt bezpośrednio, zadeklarować wartość zwracaną jako const odniesienia:

inline const string& GetLabel() const{ return m_Label; } 

2) Osoba dzwoniąca nigdy nie powinna przechowywać referencji zwróconej przez metodę klasy, powinna być używana lokalnie tylko wtedy, gdy obiekt nadrzędny jest w zasięgu.

Jeśli z jakiegoś powodu potrzebujesz rozmówców, aby móc przechowywać referencje do wewnętrznych obiektów, użyj zamiast tego inteligentnych wskaźników.

11

Znak ampersand nie jest wcześniejszy od nazwy funkcji, ale znajduje się za typem powrotu. zwraca odniesienie do string.

Wynika z tego, że osoba wywołująca tę funkcję może zmodyfikować wartość m_label przez odwołanie. Z drugiej strony unika kopiowania ciągu znaków. Może chcesz odniesienie, a funkcja będzie const, tak:

inline const string& GetLabel() const 
{ 
    return m_Label; 
} 

Najlepsze z obu światów. Unikasz kopii, ale dzwoniący nie mogą zmienić obiektu.

+0

Rzeczywiście, prawdopodobnie chcesz _but_ wersji const i non const. – ildjarn

+0

@ildjam To tylko częściowo prawda. Zwykle chcesz tylko podać wersję const, chyba że masz powód, aby pozwolić rozmówcom na modyfikowanie obiektu bezpośrednio. Jeśli udostępnisz wersję niestałą, powinieneś również podać wersję const, aby nadal można było uzyskiwać dostęp tylko do odczytu, w którym masz odwołanie do obiektu nadrzędnego. – Gerald

+1

@Gerald: Przepraszam, powinienem wyjaśnić - chodzi mi o to, że jeśli chcesz mieć wersję niestałą, która zwraca referencję, to prawie na pewno chcesz również wersji Const. – ildjarn

1

Masz rację. Jest to odniesienie do elementu string.

Implikacja polega na tym, że jeśli osoba wywołująca ma przypisać wartość lub w inny sposób zmodyfikować zwracany ciąg, to będzie również modyfikować zmienną składową. Jeśli nie jest to intencja, możesz chcieć zwrócić kopię według wartości, aby uniknąć zerwania enkapsulacji.

2

Zwrócenie odwołania oznacza, że ​​kod wywołujący może zmodyfikować wartość zmiennej członkowskiej po powrocie. To bardzo niebezpieczne, chyba że zamierzałeś, żeby tak się stało.

Lepsza jest referencja const lub zwracana przez wartość (bez wartości &).

2

Jedną z konsekwencji jest to, że jeśli obiekt otaczająca jest zniszczona, odniesienie się nieprawidłowy:

Object* o = new Object; 
string& label = o->GetLabel(); 
delete o; 
// label becomes a dangling reference here. 

Innym Wynika z tego, że rozmówca prawdopodobnie modyfikacji łańcucha. Możesz to naprawić, zwracając referencję do stałej.

Powiązane problemy