Que puis-je utiliser à la place de l'opérateur flèche, `->`?

112

À quoi sert l'opérateur flèche ( ->)?

Pennsylvanie
la source

Réponses:

148

Les deux expressions suivantes sont équivalentes:

a->b

(*a).b

(sujet à une surcharge de l'opérateur, comme le mentionne Konrad, mais c'est inhabituel).

Greg Hewgill
la source
9
Les problèmes de surcharge sont beaucoup moins inhabituels que vous ne le pensez. Il n'y a pas longtemps, STL implementors avait pas de surcharge ->opérateur pour certains types de iterator de sorte que vous aviez à utiliser *.. De nombreuses bibliothèques les définissent de manière incohérente. Cela devient vraiment ennuyeux lorsque vous travaillez avec des modèles et que vous ne connaissez pas le type précis.
Konrad Rudolph
1
vous pouvez également faire à la a[0].bplace de (*a).b. Mais ce ne serait pas aussi bien structuré.
Sellorio
2
Boy, après de nombreuses années de programmation c #, revenir au c ++ n'est pas seulement cognitif, la syntaxe c ++ est juste moche et dégueulasse. J'ai envie de prendre une douche après l'avoir utilisée. Les programmes écrits en c et c ++ encouragent simplement une mauvaise programmation. Apple, pré-unix, a eu du mal à rendre le langage aussi joli que Pascal.
ATL_DEV
@ATL_DEV Je dirais que beaucoup de choses laides ne sont plus considérées comme idiomatiques, mais malheureusement cela ne signifie pas que vous pouvez vous permettre de ne pas vous familiariser avec cela en tant que programmeur C ++. De plus, le chemin syntaxiquement agréable n'est souvent pas le chemin sémantiquement agréable, mais cela s'est aussi amélioré et non pire. Mais là encore, j'ai le syndrome de Stockholm C ++.
Tim Seguine
@TimSeguine Si jamais vous voulez voir du joli code, alors regardez la documentation pour l'intérieur du Macintosh. Je pense qu'ils ont inventé CamelCase. Noms de variables très descriptifs et code au format élégant. Ils ont réussi à rendre leur dernier code C presque aussi beau que leur précédent code Pascal.
ATL_DEV
70

a->best généralement synonyme de (*a).b. Les parenthèses ici sont nécessaires en raison de la force de liaison des opérateurs *et .: *a.bne fonctionnerait pas car la liaison .est plus forte et est exécutée en premier. C'est donc équivalent à *(a.b).

Méfiez-vous de la surcharge, cependant: comme les deux ->et *peuvent être surchargés, leur signification peut différer radicalement.

Konrad Rudolph
la source
1
Par binding strengthvous voulez dire la priorité des opérateurs? sinon quelle est la différence entre les deux?
vishnuprasanth
1
@Vizkrig Oui, les deux termes sont utilisés de manière interchangeable (bien que la «priorité des opérateurs» semble être beaucoup plus fréquente, du moins ces dernières années).
Konrad Rudolph
45

Le langage C ++ définit l'opérateur de flèche ( ->) comme synonyme de déréférencement d'un pointeur, puis utilise l' .opérateur sur cette adresse.

Par exemple:

Si vous avez un objet, anObjectet un pointeur, aPointer:

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

Pour pouvoir utiliser l'une des méthodes d'objets, vous déréférencez le pointeur et effectuez un appel de méthode sur cette adresse:

(*aPointer).method();

Ce qui pourrait être écrit avec l'opérateur flèche:

aPointer->method();

La principale raison de l'existence de l'opérateur de flèche est qu'il raccourcit la saisie d'une tâche très courante et qu'il est également assez facile d'oublier les parenthèses autour du déréférencement du pointeur. Si vous avez oublié les parenthèses, l'opérateur.-Se liera plus fort que * -operator et fera exécuter notre exemple comme:

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

Certaines des autres réponses ont également mentionné à la fois que les opérateurs C ++ peuvent être surchargés et que ce n'est pas si courant.

Pennsylvanie
la source
8
new SomeClass()renvoie un pointeur ( SomeClass *), pas l' SomeClassobjet. Et vous commencez par déclarer anObjectet aPointermais vous utilisez pensuite.
musiphil
dans l'ensemble cette explication est théoriquement très appropriée, seul le changement d'objets la rend un peu alambiquée. Mais le processus est mieux décrit
Code Man
17

En C ++ 0x, l'opérateur obtient une seconde signification, indiquant le type de retour d'une fonction ou d'une expression lambda

auto f() -> int; // "->" means "returns ..."
Johannes Schaub - litb
la source
1
Techniquement, ce n'est plus un «opérateur» là-bas, ou est-ce?
Martin Ba
6
@Martin la plupart des gens utilisent le mot «opérateur» pour de nombreuses choses qui ne sont pas directement utilisées pour calculer les valeurs. Comme pour "::" ("scope operator"). Je ne sais pas exactement quel est le point de vue de la norme à ce sujet. Dans un sens abstrait, on pourrait voir "->" comme un opérateur fonctionnel mappant une séquence de types (paramètres) à un type de retour, comme l'opérateur haskell, qui s'écrit également "->".
Johannes Schaub - lit
6
Je me rends! :-P
Martin Ba
2
@ JohannesSchaub-litb: ::est en fait un opérateur, comme .ou ->, et est appelé "opérateur de résolution de portée" dans la norme.
musiphil
13

Je le lis principalement de droite à gauche et j'appelle "in"

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

devient:

"baz in bar in foo devient croak in qux."

Tetha
la source
1

-> est utilisé lors de l'accès aux données sur lesquelles vous avez un pointeur.

Par exemple, vous pouvez créer un pointeur ptr vers une variable de type int intVar comme ceci:

int* prt = &intVar;

Vous pouvez alors utiliser une fonction, telle que foo, uniquement en déréférençant ce pointeur - pour appeler la fonction sur la variable vers laquelle pointe le pointeur, plutôt que sur la valeur numérique de l'emplacement mémoire de cette variable:

(*ptr).foo();

Sans les parenthèses ici, le compilateur comprendrait cela comme *(ptr.foo())dû à la priorité des opérateurs qui n'est pas ce que nous voulons.

C'est en fait la même chose que de taper

ptr->foo();

Comme les ->déréférences ce pointeur, et ainsi appelle la fonction foo()sur la variable vers laquelle le pointeur pointe pour nous.

De même, nous pouvons utiliser ->pour accéder ou définir un membre d'une classe:

myClass* ptr = &myClassMember;
ptr->myClassVar = 2; 
Tryb Ghost
la source
0

Vous pouvez utiliser -> pour définir une fonction.

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

Ce n'est pas un lambda. C'est vraiment une fonction. "->" indique le type de retour de la fonction.

Zhang
la source