O que posso usar em vez do operador de seta, `->`?

112

Qual é o ->sinônimo do operador de seta ( )?

PA
fonte

Respostas:

148

As duas expressões a seguir são equivalentes:

a->b

(*a).b

(sujeito à sobrecarga do operador, como Konrad menciona, mas isso é incomum).

Greg Hewgill
fonte
9
Problemas de sobrecarga são muito menos incomuns do que você pensa. Não muito tempo atrás, os implementadores de STL não tinham ->operador sobrecarregado para alguns tipos de iterador, então você tinha que usar *.. Muitas bibliotecas os definem de forma inconsistente. Fica muito chato quando você trabalha com modelos e não sabe o tipo preciso.
Konrad Rudolph,
1
você também pode fazer em a[0].bvez de (*a).b. Mas não seria tão bem estruturado.
Sellorio
2
Rapaz, depois de muitos anos de programação em c #, voltar para c ++ não é apenas cognitivamente desgastante, a sintaxe de c ++ é simplesmente feia e nojenta. Tenho vontade de tomar banho depois de usar. Programas escritos em c e c ++ apenas encorajam a má programação. A Apple, pré-unix, lutou para tornar a linguagem tão bonita quanto Pascal.
ATL_DEV
@ATL_DEV Eu diria que muitas das coisas feias não são mais consideradas idiomáticas, mas infelizmente isso não significa que você pode se dar ao luxo de não estar familiarizado com elas como um programador C ++ praticante. Além disso, o caminho sintaticamente bom geralmente não é o caminho semanticamente bom, mas isso também está melhorando, não piorando. Mas, novamente, tenho a Síndrome de Estocolmo C ++.
Tim Seguine
@TimSeguine Se você quiser ver um código bonito, consulte a documentação do Macintosh. Acho que inventaram o CamelCase. Nomes de variáveis ​​muito descritivos e código formatado com elegância. Eles conseguiram tornar seu código C posterior quase tão lindo quanto o código Pascal anterior.
ATL_DEV
70

a->bgeralmente é um sinônimo de (*a).b. Os parênteses aqui são necessários por causa da força de ligação dos operadores *e .: *a.bnão funcionaria porque .se liga mais forte e é executado primeiro. Isso é, portanto, equivalente a *(a.b).

No entanto, cuidado com a sobrecarga: como ->e *pode ser sobrecarregado, seu significado pode diferir drasticamente.

Konrad Rudolph
fonte
1
Por binding strengthque você quer dizer a precedência de operador? se não, qual é a diferença entre os dois?
vishnuprasanth
1
@Vizkrig Sim, os dois termos são usados ​​alternadamente (embora “precedência de operador” pareça ser muito mais frequente, pelo menos nos últimos anos).
Konrad Rudolph,
45

A linguagem C ++ - define o operador de seta ( ->) como um sinônimo para desreferenciar um ponteiro e, em seguida, usa o .operador de seta nesse endereço.

Por exemplo:

Se você tem um objeto, anObjecte um ponteiro, aPointer:

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

Para poder usar um dos métodos de objetos, desreferencie o ponteiro e faça uma chamada de método nesse endereço:

(*aPointer).method();

Que pode ser escrito com o operador de seta:

aPointer->method();

A principal razão da existência do operador de seta é que ele encurta a digitação de uma tarefa muito comum e também meio que fácil esquecer os parênteses em torno da desreferenciação do ponteiro. Se você esquecer os parênteses, o operador.-Se vinculará com mais força do que o operador * e fará com que nosso exemplo seja executado como:

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

Algumas das outras respostas também mencionaram que os operadores C ++ podem ser sobrecarregados e que isso não é tão comum.

PA
fonte
8
new SomeClass()retorna um ponteiro ( SomeClass *), não o SomeClassobjeto. E você começa declarando anObjecte, aPointermas está usando pdepois.
musiphil
no geral, essa explicação é teoricamente muito adequada, apenas a mudança de objetos a torna um pouco complicada. Mas o processo é melhor descrito
Code Man
17

Em C ++ 0x, o operador obtém um segundo significado, indicando o tipo de retorno de uma função ou expressão lambda

auto f() -> int; // "->" means "returns ..."
Johannes Schaub - litb
fonte
1
Especificar tecnicamente que não é mais um "operador" aí, ou é?
Martin Ba
6
@Martin a maioria das pessoas usa a palavra "operador" para muitas coisas que não são usadas diretamente para calcular valores. Como para "::" ("operador de escopo"). Não sei qual é o ponto de vista da norma sobre isso, exatamente. Em um sentido abstrato, pode-se ver "->" como um operador funcional que mapeia uma seqüência de tipos (parâmetros) para um tipo de retorno, como o operador haskell, que também é escrito "->".
Johannes Schaub - litb
6
Eu me rendo! :-P
Martin Ba
2
@ JohannesSchaub-litb: ::é na verdade um operador, como .ou ->, e é chamado de "operador de resolução de escopo" no padrão.
musiphil
13

Eu leio principalmente da direita para a esquerda e chamo "em"

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

torna-se:

"baz em bar em foo torna-se coak em qux."

Tetha
fonte
1

-> é usado para acessar dados para os quais você tem um ponteiro.

Por exemplo, você pode criar um ponteiro ptr para a variável do tipo int intVar como este:

int* prt = &intVar;

Você poderia então usar uma função, como foo, nela apenas desreferenciando esse ponteiro - para chamar a função na variável para a qual o ponteiro aponta, ao invés do valor numérico da localização da memória dessa variável:

(*ptr).foo();

Sem os parênteses aqui, o compilador entenderia isso como *(ptr.foo())devido à precedência do operador que não é o que queremos.

Na verdade, isso é o mesmo que digitar

ptr->foo();

Como o ->desreferencia esse ponteiro, chama a função foo()na variável para a qual o ponteiro está apontando para nós.

Da mesma forma, podemos usar ->para acessar ou definir um membro de uma classe:

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

Você pode usar -> para definir uma função.

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

Não é um lambda. É realmente uma função. "->" indica o tipo de retorno da função.

Zhang
fonte