¿Qué puedo usar en lugar del operador de flecha, `->`?

112

¿Cuál es el ->sinónimo del operador de flecha ( )?

Pensilvania
fuente

Respuestas:

148

Las siguientes dos expresiones son equivalentes:

a->b

(*a).b

(sujeto a sobrecarga del operador, como menciona Konrad, pero eso es inusual).

Greg Hewgill
fuente
9
Los problemas de sobrecarga son mucho menos inusuales de lo que cree. No hace mucho, los implementadores de STL no tenían un ->operador sobrecargado para algunos tipos de iteradores, por lo que tenía que usar *.. Muchas bibliotecas los definen de manera inconsistente. Se vuelve realmente molesto cuando trabaja con plantillas y no conoce el tipo exacto.
Konrad Rudolph
1
también puedes hacer en a[0].blugar de (*a).b. Pero no estaría tan bien estructurado.
Sellorio
2
Vaya, después de muchos años de programación en C #, volver a C ++ no solo es agotador cognitivamente, la sintaxis de C ++ es simplemente fea y asquerosa. Tengo ganas de darme una ducha después de usarlo. Los programas escritos en C y C ++ simplemente fomentan la mala programación. Apple, antes de unix, luchó por hacer que el lenguaje fuera tan bonito como Pascal.
ATL_DEV
@ATL_DEV Yo diría que muchas de las cosas feas ya no se consideran idiomáticas, pero desafortunadamente eso no significa que pueda darse el lujo de no estar familiarizado con ellas como programador en C ++. Además, la ruta sintácticamente agradable a menudo no es la ruta semánticamente agradable, pero también ha ido mejorando, no empeorando. Pero, de nuevo, tengo el síndrome de Estocolmo C ++.
Tim Seguine
@TimSeguine Si alguna vez desea ver un código bonito, consulte la documentación del interior de Macintosh. Creo que inventaron CamelCase. Nombres de variables muy descriptivos y código elegantemente formateado. Se las arreglaron para hacer su código C posterior casi tan hermoso como su código Pascal anterior.
ATL_DEV
70

a->bes generalmente un sinónimo de (*a).b. Los paréntesis aquí son necesarios debido a la fuerza de enlace de los operadores *y .: *a.bno funcionaría porque se .enlaza más fuerte y se ejecuta primero. Esto es, por tanto, equivalente a *(a.b).

Sin embargo, tenga cuidado con la sobrecarga: dado que ambos ->y *pueden sobrecargarse, su significado puede diferir drásticamente.

Konrad Rudolph
fuente
1
¿ binding strengthTe refieres a la precedencia del operador? si no, ¿cuál es la diferencia entre los dos?
vishnuprasanth
1
@Vizkrig Sí, los dos términos se usan indistintamente (aunque la “precedencia de operadores” parece ser mucho más frecuente, al menos en los últimos años).
Konrad Rudolph
45

El lenguaje C ++ define el operador de flecha ( ->) como sinónimo de desreferenciar un puntero y luego usa el .operador -en esa dirección.

Por ejemplo:

Si usted tiene un objeto, anObjecty un puntero, aPointer:

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

Para poder usar uno de los métodos de objetos, elimine la referencia del puntero y realice una llamada al método en esa dirección:

(*aPointer).method();

Que podría escribirse con el operador de flecha:

aPointer->method();

La razón principal de la existencia del operador de flecha es que acorta la escritura de una tarea muy común y también es fácil olvidar los paréntesis alrededor de la desreferenciación del puntero. Si olvidó los paréntesis, el.-Operator se vinculará más fuerte que * -operator y hará que nuestro ejemplo se ejecute como:

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

Algunas de las otras respuestas también han mencionado que los operadores de C ++ pueden estar sobrecargados y que no es tan común.

Pensilvania
fuente
8
new SomeClass()devuelve un puntero ( SomeClass *), no el SomeClassobjeto. Y comienzas declarando anObjecty luego aPointerusas p.
Musiphil
En general, esta explicación es teóricamente muy adecuada, solo el cambio de objetos la hace un poco complicada. Pero el proceso está mejor descrito
Code Man
17

En C ++ 0x, el operador obtiene un segundo significado, que indica el tipo de retorno de una función o expresión lambda

auto f() -> int; // "->" means "returns ..."
Johannes Schaub - litb
fuente
1
Técnicamente, el moteado ya no es un "operador" allí, ¿o no?
Martin Ba
6
@Martin la mayoría de la gente usa la palabra "operador" para muchas cosas que no se usan directamente para calcular valores. Como para "::" ("operador de alcance"). No sé exactamente cuál es el punto de vista de la norma sobre esto. En un sentido abstracto, uno podría ver "->" como un operador funcional que mapea una secuencia de tipos (parámetros) a un tipo de retorno, como el operador haskell, que también se escribe "->".
Johannes Schaub - litb
6
¡Me rindo! :-P
Martin Ba
2
@ JohannesSchaub-litb: ::es en realidad un operador, como .or ->, y se llama "operador de resolución de alcance" en el estándar.
Musiphil
13

Lo leo principalmente de derecha a izquierda y llamo "en"

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

se convierte en:

"baz in bar in foo se convierte en croak in qux".

Tetha
fuente
1

-> se usa al acceder a datos a los que tiene un puntero.

Por ejemplo, podría crear un puntero ptr a una variable de tipo int intVar como este:

int* prt = &intVar;

Luego, podría usar una función, como foo, en él solo desreferenciando ese puntero, para llamar a la función en la variable a la que apunta el puntero, en lugar de en el valor numérico de la ubicación de memoria de esa variable:

(*ptr).foo();

Sin los paréntesis aquí, el compilador entendería que esto se *(ptr.foo())debe a la precedencia del operador, que no es lo que queremos.

En realidad, esto es lo mismo que escribir

ptr->foo();

Como ->elimina la referencia a ese puntero, y así llama a la función foo()de la variable a la que apunta el puntero.

De manera similar, podemos usar ->para acceder o configurar un miembro de una clase:

myClass* ptr = &myClassMember;
ptr->myClassVar = 2; 
Tryb Fantasma
fuente
0

Puede usar -> para definir una función.

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

No es una lambda. Realmente es una función. "->" indica el tipo de retorno de la función.

Zhang
fuente