Ponteiros, Referências e Classes em C++

  1. Operadores fundamentais: & e *

Em C++, o operador & retorna o endereço de uma variável, enquanto o operador * pode declarar um ponteiro ou acessar o valor apontado por ele.

#include <iostream>

int main()
{
    int x = 10, y = 20;
    int* ptrX = &x;
    int* ptrY = &y;

    std::cout << "Endereco de x: " << ptrX << "\n";
    std::cout << "Valor de x: " << *ptrX << "\n";
    return 0;
}

  1. Ponteiros e referências

Apesar de ambos permitirem acessar um objeto indiretamente, possuem semânticas distintas:

  • Ponteiro: variável que armazena um endereço. Pode ser reatribuído, aceitar nullptr e ter múltiplos níveis.
  • Referência: apelido para uma variável já existente. Deve ser inicializada e nunca muda de objeto vinculado.
int valor = 42;
int* p = &valor;     // ponteiro
int& r = valor;       // referência: apelido de valor

std::cout << *p;      // 42
std::cout << r;       // 42

Outras diferenças importantes:

  • sizeof(r) retorna o tamanho do objeto referenciado; sizeof(p) retorna o tamanho do próprio ponteiro.
  • O operador ++ em um ponteiro avança para o próximo elemento do tipo apontado; em uma referência incrementa o valor do objeto.
  • Ponteiros admitem várias qualificações const (const int*, int* const); referências não podem ser reseatadas, apenas vinculadas a objetos const.
  1. struct versus class

Em C++, struct e class são quase idênticos, mas existem duas diferenças principais:

  1. A visibilidade padrão em struct é public; em class, private.
  2. Em tepmlates, o parâmetro de tipo deve ser declarado com class ou typename, não struct.

Uma struct pode conter um ponteiro para seu próprio tipo, mas não uma instância direta, pois o tipo ainda está incompleto naquele ponto.

Quando usar cada um:

  • struct: agregados leves que basicamente armazenam dados, como coordenadas, retângulos ou registros simples.
  • class: entidades com lógica complexa, invariantes, encapsulamento e hierarquias de herança.
  1. Passagem e retorno de objetos

Passar um objeto diretamente por valor copia todos os seus membros, o que pode ser custoso e desnecessário:

void func(Objeto obj);              // copia: evitar
void func(Objeto* obj);             // ponteiro: pode ser nulo
void func(Objeto& obj);             // referência: não nulo
void func(const Objeto& obj);        // referência const: leitura eficiente

Ao retornar um objeto, retornar referência ou ponteiro evita construções de cópia, desde que o objeto retornado continue existindo fora da função. Nunca retorne referência para variável local.

Para impedir cópias indesejadas, torne o construtor de cópia privado (em C++11 e posteriores, use = delete).

  1. Atribuição, criação e exemplo prático

A atribuição entre objetos copia o estado dos membros de dados; funções-membro não são copiadas. Se a classe gerencia memória dinâmica, deve-se implementar o construtor de cópia e o operador de atribuição para evitar cópias rasas.

Podemos criar objetos na pilha ou no heap:

Objeto o;                  // pilha
Objeto* p = new Objeto();  // heap: lembre-se de delete

Exemplo ilustrando ponteiro para objeto:

#include <iostream>

class Ponto {
public:
    int x;
    int y;
};

class Caixa {
public:
    Ponto* ref;

    void vincula(Ponto& p) {
        ref = &p;
        p.x = 5;
        p.y = 9;
        std::cout << ref->x << "\n";
        std::cout << ref->y << "\n";
    }
};

int main() {
    Ponto* p = new Ponto();
    p->x = 1;
    p->y = 2;

    Caixa* c = new Caixa();
    c->vincula(*p);

    delete p;
    delete c;
    return 0;
}

Tags: C++ ponteiros referências struct Class

Publicado em 9-17 21:51