Що я можу використовувати замість оператора стрілки `->`?


112

Що таке оператор стрілки ( ->) синонім?

Відповіді:


148

Наступні два вирази еквівалентні:

a->b

(*a).b

(за умови перевантаження оператора, як згадує Конрад, але це незвично).


9
Питання щодо перевантаження набагато менш незвичні, ніж ви думаєте. Не так давно реалізатори STL не мали перевантаженого ->оператора для деяких типів ітераторів, тому вам довелося користуватися *.. Багато бібліотек визначають їх непослідовно. Стає по-справжньому дратує, коли ви працюєте з шаблонами і не знаєте точного типу.
Конрад Рудольф

1
ви також можете робити a[0].bзамість цього (*a).b. Але це було б не так правильно.
Sellorio

2
Хлопчик, після багатьох років програмування c #, повернення до c ++ - це не тільки когнітивно оподаткування, синтаксис c ++ - просто потворний і приємний. Я відчуваю, що приймаю душ після його використання. Програми, написані на c і ​​c ++, просто сприяють поганому програмуванню. Apple, перед Unix, намагалася зробити мову такою ж красивою, як Паскаль.
ATL_DEV

@ATL_DEV Я б заперечував, що багато негарних речей вже не вважаються ідіоматичними, але, на жаль, це не означає, що ви можете дозволити собі не бути знайомими з ним як практикуючий програміст на C ++. Крім того, синтаксично приємний шлях часто не є семантично приємним шляхом, але це також покращується не гірше. Але знову-таки у мене синдром С ++ Стокгольм.
Тім Сегейн

@TimSeguine Якщо ви хочете побачити гарний код, перегляньте документацію Macintosh. Я думаю, що вони винайшли CamelCase. Дуже описові назви змінних та елегантно відформатований код. Їм вдалося зробити свій пізніше код C майже таким же чудовим, як і їх попередній код Pascal.
ATL_DEV

70

a->bвзагалі є синонімом для (*a).b. Дужки тут потрібні через силу зв'язування операторів *і .: *a.bне працюватимуть, тому що .зв'язується сильніше і виконується першим. Таким чином, це рівнозначно *(a.b).

Остерігайтеся перевантаження, хоча: Так як ->і *можуть бути перевантажені, їх зміст може істотно відрізнятися.


1
До binding strengthви маєте в виду оператор пріоритет? якщо ні, то яка різниця між ними?
vishnuprasanth

1
@Vizkrig Так, ці два терміни вживаються взаємозамінно (хоча, здається, «пріоритет оператора» набагато частіше, принаймні в останні роки).
Конрад Рудольф

45

Мова C ++ визначає оператор стрілки ( ->) як синонім перенаправлення покажчика, а потім використовує .-operator за цією адресою.

Наприклад:

Якщо у вас є об'єкт anObjectі вказівник, aPointerвиконайте вказані нижче дії :

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

Щоб мати можливість використовувати один з методів об'єктів, ви відмежуєте покажчик і виконайте виклик методу за цією адресою:

(*aPointer).method();

Що можна записати за допомогою оператора стрілки:

aPointer->method();

Основна причина існування оператора стрілки полягає в тому, що це скорочує введення дуже поширеного завдання, а також легко забути дужки навколо перенаправлення вказівника. Якщо ви забули круглі дужки,. -Оператор прив’яже сильніше, ніж * -operator, і зробить наш приклад виконаним як:

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

Деякі інші відповіді також згадують про те, що оператори C ++ можуть бути перевантажені і що це не так часто.


8
new SomeClass()повертає вказівник ( SomeClass *), а не SomeClassоб’єкт. І ви починаєте з декларуванням anObjectі , aPointerале ви використовуєте pзгодом.
musiphil

загалом це пояснення теоретично дуже влучне, лише зміна об'єктів робить його дещо викривленим. Але процес краще описаний
Code Man

17

У C ++ 0x оператор отримує друге значення, що вказує на тип повернення функції або лямбда-вираз

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

1
З технічної точки зору це вже не "оператор", чи це?
Мартін Ба

6
@Martin більшість людей використовують слово "оператор" для багатьох речей, які не використовуються безпосередньо для обчислення значень. Як і для "::" ("оператор області"). Я точно не знаю, яка точка зору стандарту саме на це. В абстрактному сенсі можна побачити "->" як функціональний оператор, який відображає послідовність типів (параметрів) до типу повернення, як оператор haskell, який також записаний "->".
Йоханнес Шауб - ліб

6
Я здаюся! :-P
Мартін Ба

2
@ JohannesSchaub-litb: ::насправді оператор, як-от .або ->, і називається в стандарті "оператором роздільної здатності".
musiphil

13

Я здебільшого читаю це справа наліво і дзвоню "в"

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

стає:

"baz in bar in foo стає кривим у qux."


1

-> використовується для доступу до даних, на які ви маєте вказівник.

Наприклад, ви можете створити вказівник ptr на змінну типу int intVar, як це:

int* prt = &intVar;

Тоді ви можете використовувати функцію, таку як foo, на ній лише шляхом перенаправлення цього вказівника - для виклику функції на змінній, на яку вказує вказівник, а не на числове значення місця пам'яті цієї змінної:

(*ptr).foo();

Без дужок тут компілятор зрозумів би це як *(ptr.foo())перевагу оператора, яке не є тим, що ми хочемо.

Це насправді так само, як і друкувати

ptr->foo();

Як ->відміни, що foo()вказують , і так називає функцію змінної, на яку вказує нам вказівник.

Так само ми можемо використовувати ->для доступу або встановлення члена класу:

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

0

Ви можете використовувати -> для визначення функції.

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

Це не лямбда. Це дійсно функція. "->" вказує тип повернення функції.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.