Mecanismos de Passagem de Parâmetros em C++

Passagem por Valor

Na passagem por valor, o compilador cria uma cópia local do dado original e a armazena em um novo endereço de memória dentro do escopo da função. Quaisquer modificações realizadas no parâmetro afetam apenas essa cópia, preservando a variável original intacta.

Considerações:

  • Segurança: Garante que a função não altere o estado da variável externa.
  • Desempenho: Para tipos primitivos (como int ou double), o custo é desprezível. Contudo, para objetos grandes ou coleções (como std::vector), a cópia pode gerar um overhead significativo de memória e processamento.
void calcularDobro(int numero) {
    numero = numero * 2; // Altera apenas a cópia local
}

int valor = 10;
calcularDobro(valor);
// Após a execução, 'valor' continua sendo 10.

Passagem por Ponteiro (Endereço)

Nesta abordagem, o que é enviado para a função é o endereço de memória da variável original. O parâmetro da função é um ponteiro que aponta para o local onde o dado reside. Através do operador de desreferenciação (*), a função pode acessar e manipular diretamente o valor original.

Considerações:

  • Eficiência: Apenas o endereço (geralmente 4 ou 8 bytes) é copiado, independentemente do tamanho do objeto apontado.
  • Flexibilidade: Permite passar nullptr para indicar a ausência de um valor.
  • Risco: Exige verificações de segurança para evitar o acesso a ponteiros nulos ou inválidos.
void resetarValor(int* ptr) {
    if (ptr != nullptr) {
        *ptr = 0; // Modifica o valor no endereço original
    }
}

int contador = 50;
resetarValor(&contador); 
// O endereço de 'contador' é passado. Agora 'contador' é 0.

Passagem por Referência

A passagem por referência funicona como a criação de um apelido (alias) para a variável original. Embora tecnicamente o compilador use endereços por debaixo dos panos, a sintaxe é idêntica à da passagem por valor, mas sem a criação de cópias dos dados.

Considerações:

  • Sintaxe Limpa: Evita o uso excessivo de operadores de ponteiro, tornando o código mais legível.
  • Segurança Adicional: Referências não podem ser nulas e devem ser inicializadas obrigatoriamente, o que reduz erros comuns encontrados em ponteiros.
  • Const References: O uso de const T& é uma prática padrão em C++ para passar objetos grandes de forma eficiente, garantindo que eles não sejam modificados acidentalmente.
void adicionarSufixo(std::string& texto) {
    texto += "_processado"; // Modifica a string original diretamente
}

std::string log = "dados";
adicionarSufixo(log);
// 'log' agora contém "dados_processado".

Critérios de Escolha

Para otimizar o desenvolvimento em C++, recomenda-se seguir estas diretrizes:

  1. Tipos Primitivos: Utilize passagem por valor. O custo de copiar um inteiro é muitas vezes menor do que o custo de mainpular endereços de memória.
  2. Objetos e Estruturas Médias/Grandes:
    • Se a função não deve alterar o objeto: use const T& (referência constante).
    • Se a função precisa modificar o objeto oriignal: use referência (T&).
  3. Opcionalidade: Se o parâmetro for opcional ou se você precisar lidar com lógica de memória de baixo nível, utilize ponteiros para permitir a passagem de nullptr.

Tags: C++ Memory Management pointers references Software Architecture

Publicado em 9-29 14:55