Respostas:
As duas expressões a seguir são equivalentes:
a->b
(*a).b
(sujeito à sobrecarga do operador, como Konrad menciona, mas isso é incomum).
a[0].b
vez de (*a).b
. Mas não seria tão bem estruturado.
a->b
geralmente é 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.b
nã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.
binding strength
que você quer dizer a precedência de operador? se não, qual é a diferença entre os dois?
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, anObject
e 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.
new SomeClass()
retorna um ponteiro ( SomeClass *
), não o SomeClass
objeto. E você começa declarando anObject
e, aPointer
mas está usando p
depois.
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 ..."
::
é na verdade um operador, como .
ou ->
, e é chamado de "operador de resolução de escopo" no padrão.
->
é 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;
->
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.