Qual é o significado de * e & quando aplicado a nomes de variables?

Em C ++, qual é a diferença entre:

void func(MyType&); // declaration //... MyType * ptr; func(*ptr); // compiler doesnt give error func(ptr); // compiler gives error i thought & represents memory address so // this statement should correct as ptr is only a pointer // or address of some real var. 

O operador de prefixo unário & , quando aplicado a um object, produz o endereço do object: &obj .
O modificador de tipo & , quando aplicado a uma variável prestes a ser declarada, modificará o tipo da variável para ser um tipo de referência : int& .

O mesmo se aplica a * : quando aplicado como um operador de prefixo unário a um ponteiro, ele cancelará a referência ao ponteiro, produzindo o object referido: *ptr .
Quando usado como um modificador de tipo para uma variável prestes a ser declarada, * modificará o tipo para ser um ponteiro : int* .

De maneira semelhante, o modificador type [] aplicado a uma variável que está sendo declarada modificará o tipo da variável para um array, enquanto o operador infix binário [] aplicado a um object do tipo array irá acessar um dos sub-objects do array.


Não é útil que os modificadores de tipo se apliquem à variável declarada , não ao tipo com o qual são declarados. Por exemplo, isso

 int *p, **pp, i, a[10], &r = i; 

define um ponteiro int , um ponteiro para um ponteiro para um int , um vanilla int , um array de 10 int e uma referência int . (O último é imediatamente inicializado, porque você não pode ter uma referência não inicializada.) Observe que os modificadores de tipo sintaticamente pertencem à variável declarada cujo tipo eles estão modificando, não ao tipo da variável declarada. No entanto, os modificadores de tipo ( * e & ) modificam o tipo da variável.
No seguinte caso, no entanto, com p , i presume-se que sejam variables ​​que já foram declaradas

 *pp = &i; a[0] = i; 

* e & são operadores de prefixo unários desreferenciando pp e produzindo o endereço de i , enquanto [] produz o primeiro object int na matriz a .

O fato de C e C ++ não se importarem com os espaços em branco em torno dos modificadores de tipo e que isso levou a campos diferentes quando se trata de colocá-los realmente não facilita as coisas.
Algumas pessoas colocam os modificadores de tipo perto do tipo. Eles argumentam que modifica o tipo e por isso deve ir para lá:

 int* ptr; 

A desvantagem é que isso se torna confuso ao declarar vários objects. este

 int* a, b; 

define a para ser um ponteiro para int , mas b para ser um int . É por isso que algumas pessoas preferem escrever

 int *ptr; int *a, *b; 

Sugiro simplesmente nunca declarar vários objects na mesma instrução. IMO que torna o código mais fácil de ler. Além disso, deixa você livre para escolher qualquer convenção.


Para complicar ainda mais as coisas, além dos modificadores de tipo e dos operadores unários de prefixo & e * , existem também os operadores binário infix & e * , significando “bit a bit AND” e “multiplicação”. E para adicionar insulto à injúria, em C ++ você pode sobrecarregar tanto o prefixo unário quanto as variantes infixos binárias desses operadores (e o infixo binário [] ) para tipos definidos pelo usuário e serem completamente livres quanto à sua semântica.

MyType & representa um / reference /, um animal completamente diferente para pointers. Se o seu protótipo de function fosse

func (MyType);

você estaria trabalhando com uma cópia do argumento dentro da function. Com

func (MyType &);

você está trabalhando com o object em si (isto é, o mesmo object no escopo chamado e chamado). É, neste caso, como trabalhar com um ponteiro, mas usando a mesma syntax de “ponto” que para objects.

Claro, esta é uma explicação superficial e simplista. Para mim, compreender os profundos zeros abaixo dos pointers, referências e o resto da horda levou anos.