Czego mogę użyć zamiast operatora strzałki, `->`?


Odpowiedzi:


148

Następujące dwa wyrażenia są równoważne:

a->b

(*a).b

(z zastrzeżeniem przeciążenia operatora, jak wspomina Konrad, ale to nietypowe).


9
Problemy z przeciążeniem są dużo mniej niezwykłe, niż myślisz. Niedawno implementatorzy STL nie mieli przeciążonego ->operatora dla niektórych typów iteratorów, więc trzeba było użyć *.. Wiele bibliotek definiuje je niespójnie. Staje się naprawdę irytujące, gdy pracujesz z szablonami i nie znasz dokładnego typu.
— Konrad Rudolph

1
możesz też zrobić a[0].bzamiast (*a).b. Ale nie byłby tak odpowiednio skonstruowany.
— Sellorio

2
Chłopcze, po wielu latach programowania w C #, powrót do C ++ jest nie tylko obciążeniem poznawczym, składnia c ++ jest po prostu brzydka i obrzydliwa. Po użyciu mam ochotę wziąć prysznic. Programy napisane w c i c ++ po prostu zachęcają do złego programowania. Apple starał się uczynić język tak pięknym jak Pascal.
— ATL_DEV,

@ATL_DEV Twierdzę, że wiele brzydkich rzeczy nie jest już uważanych za idiomatyczne, ale niestety nie oznacza to, że możesz sobie pozwolić na to, aby nie znać ich jako praktykującego programistę C ++. Ścieżka ładna składniowo często nie jest ścieżką ładną semantycznie, ale ona też jest coraz lepsza, a nie gorsza. Ale znowu mam C ++ Stockholm Syndrome.
— Tim Seguine

@TimSeguine Jeśli kiedykolwiek chcesz zobaczyć ładny kod, spójrz do dokumentacji wewnątrz Macintosha. Myślę, że wymyślili CamelCase. Bardzo opisowe nazwy zmiennych i elegancko sformatowany kod. Udało im się uczynić ich późniejszy kod C prawie tak wspaniały, jak ich wcześniejszy kod Pascal.
— ATL_DEV

70

a->bjest generalnie synonimem (*a).b. Nawiasy są tutaj konieczne ze względu na siłę wiązania operatorów, *a .: *a.bnie zadziała, ponieważ .wiąże się silniej i jest wykonywany jako pierwszy. Jest to zatem równoważne z *(a.b).

Uważaj jednak na przeciążenie: ponieważ oba ->i *mogą być przeciążone, ich znaczenie może się drastycznie różnić.


1
Przez binding strengthto znaczy pierwszeństwo operatora? jeśli nie, jaka jest różnica między nimi?
— vishnuprasanth

1
@Vizkrig Tak, te dwa terminy są używane zamiennie (chociaż „pierwszeństwo operatorów” wydaje się być znacznie częstsze, przynajmniej w ostatnich latach).
— Konrad Rudolph

45

Język C ++ - definiuje operator strzałki ( ->) jako synonim do wyłuskiwania wskaźnika, a następnie używa operatora .-operatora na tym adresie.

Na przykład:

Jeśli masz obiekt anObjecti wskaźnik aPointer:

SomeClass anObject = new SomeClass();
SomeClass *aPointer = &anObject;

Aby móc użyć jednej z metod obiektów, wyłuskujemy wskaźnik i wykonujemy wywołanie metody na tym adresie:

(*aPointer).method();

Które można zapisać za pomocą operatora strzałki:

aPointer->method();

Głównym powodem istnienia operatora strzałki jest to, że skraca on wpisywanie bardzo powszechnego zadania, a także dość łatwo zapomnieć o nawiasach wokół dereferencji wskaźnika. Jeśli zapomniałeś o nawiasach, operator.-Połączy się silniej niż * -operator i sprawi, że nasz przykład zostanie wykonany jako:

*(aPointer.method()); // Not our intention!

Niektóre z innych odpowiedzi wspominają również, że operatory C ++ mogą być przeciążone i że nie jest to tak powszechne.


8
new SomeClass()zwraca wskaźnik ( SomeClass *), a nie SomeClassobiekt. Zaczynasz od zadeklarowania, anObjecta potem aPointerużywasz p.
— musiphil

Ogólnie to wyjaśnienie jest teoretycznie bardzo trafne, tylko zmiana obiektów powoduje, że jest ono trochę zagmatwane. Ale proces jest lepiej opisany
— Code Man

17

W języku C ++ 0x operator otrzymuje drugie znaczenie, wskazujące typ zwracanej funkcji lub wyrażenia lambda

auto f() -> int; // "->" means "returns ..."

1
Technicznie rzecz biorąc, nie jest już tam „operatorem”, czy nie?
— Martin Ba

6
@Martin większość ludzi używa słowa „operator” do wielu rzeczy, które nie są bezpośrednio używane do obliczania wartości. Podobnie jak w przypadku „::” („operator zasięgu”). Nie wiem, jaki jest punkt widzenia normy w tej sprawie. W sensie abstrakcyjnym można by postrzegać „->” jako operator funkcyjny odwzorowujący sekwencję typów (parametrów) na typ zwracany, podobnie jak operator haskell, który również jest zapisywany jako „->”.
— Johannes Schaub - litb

6
Poddaję się! :-P
— Martin Ba

2
@ JohannesSchaub-litb: ::jest w rzeczywistości operatorem, takim jak .or ->, i jest w standardzie nazywany „operatorem rozpoznawania zakresu”.
— musiphil

13

Najczęściej czytam od prawej do lewej i wołam „in”

foo->bar->baz = qux->croak

staje się:

"Baz in bar in foo staje się rechocząc w qux."


1

-> jest używany podczas uzyskiwania dostępu do danych, do których masz wskaźnik.

Na przykład, możesz utworzyć wskaźnik ptr do zmiennej typu int intVar w następujący sposób:

int* prt = &intVar;

Możesz wtedy użyć funkcji, takiej jak foo, na niej tylko przez wyłuskiwanie tego wskaźnika - aby wywołać funkcję na zmiennej, na którą wskazuje wskaźnik, zamiast na wartości liczbowej lokalizacji pamięci tej zmiennej:

(*ptr).foo();

Bez nawiasów tutaj kompilator zrozumiałby to jako *(ptr.foo())wynikający z pierwszeństwa operatorów, czego nie chcemy.

W rzeczywistości jest to to samo, co pisanie

ptr->foo();

Jako ->dereferences ten wskaźnik, a więc wywołuje funkcję foo()na zmiennej, na którą wskazuje wskaźnik dla nas.

Podobnie możemy użyć, ->aby uzyskać dostęp lub ustawić członka klasy:

myClass* ptr = &myClassMember;
ptr->myClassVar = 2; 

0

Możesz użyć ->, aby zdefiniować funkcję.

auto fun() -> int
{
return 100;
}

To nie jest lambda. To naprawdę funkcja. „->” wskazuje zwracany typ funkcji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.