Pergunta

Quais são os benefícios de passar pelo ponteiro sobre passando por referência em C ++?

Ultimamente, tenho visto uma série de exemplos que escolheram passar argumentos de função por ponteiros em vez de passar por referência. Existem benefícios para fazer isso?

Exemplo:

func(SPRITE *x);

com uma chamada de

func(&mySprite);

vs.

func(SPRITE &x);

com uma chamada de

func(mySprite);
Foi útil?

Solução

Um ponteiro pode receber um parâmetro NULL, um parâmetro de referência não pode. Se há sempre uma chance de que você poderia querer passar "nenhum objeto", em seguida, usar um ponteiro em vez de uma referência.

Além disso, passando pelo ponteiro permite que você veja explicitamente no site da chamada se o objeto é passado por valor ou por referência:

// Is mySprite passed by value or by reference?  You can't tell 
// without looking at the definition of func()
func(mySprite);

// func2 passes "by pointer" - no need to look up function definition
func2(&mySprite);

Outras dicas

Passando pelo ponteiro

  • Caller tem de ter o endereço -> não transparente
  • A 0 valor pode ser fornecido a nothing média. Isso pode ser usado para fornecer argumentos opcionais.

passar por referência

  • Caller apenas passa o objeto -> transparente. Tem que ser usado para a sobrecarga de operador, uma vez que a sobrecarga para tipos de ponteiro não é possível (ponteiros são builtin tipos). Então você não pode fazer string s = &str1 + &str2; usando ponteiros.
  • Não 0 valores possíveis - função> Chamado não tem que verificá-los
  • A referência a const também aceita temporários:. void f(const T& t); ... f(T(a, b, c));, ponteiros não podem ser usados ??como que desde que você não pode tomar o endereço de um temporária
  • Por último, mas não menos importante, as referências são mais fáceis de usar -> menos chance de erros
  • .

O Allen Holub "corda suficiente para atirar no próprio pé" lista as 2 regras seguintes:

120. Reference arguments should always be `const`
121. Never use references as outputs, use pointers

Ele enumera várias razões pelas quais as referências foram adicionados ao C ++:

  • eles são necessários para definir construtores de cópia
  • são necessários para sobrecargas de operador
  • referências const permitir que você tenha semântica passagem por valor, evitando uma cópia

Seu ponto principal é que as referências não devem ser usados ??como parâmetros de 'saída', porque no site da chamada não há nenhuma indicação de se o parâmetro é uma referência ou um parâmetro de valor. Assim, sua regra é apenas referências utilização const como argumentos.

Pessoalmente, acho que esta é uma boa regra de ouro, uma vez que torna mais clara quando um parâmetro é um parâmetro de saída ou não. No entanto, enquanto eu, pessoalmente, concordo com isso, em geral, eu me permitir ser influenciado pela opinião dos outros sobre a minha equipa se eles defendem parâmetros de saída como referências (alguns desenvolvedores como eles imensamente).

I como o raciocínio por um artigo do "cplusplus.com:"

  1. passagem por valor quando a função não deseja modificar o parâmetro e o valor é fácil de cópia (ints, duplas, char, bool, etc ... tipos simples. Std :: string, std :: vetor, e todos os outros contêineres STL não são tipos simples.)

  2. Passe pelo ponteiro const quando o valor é caro para copiar e a função não deseja modificar o valor apontado E NULL seja, um valor esperado válido que as alças de função.

  3. Passe pelo ponteiro não-const quando o valor é caro para copiar e a função quer modificar o valor apontado E NULL é um valor válido, espera-se que as alças de função.

  4. passar por referência const quando o valor é caro para copiar e a função não deseja modificar o valor referido e nulos não seria um valor válido se um ponteiro foi usado.

  5. passar por referência não cont quando o valor é caro para copiar e a função quer modificar o valor referido e nulos não seria um valor válido se um ponteiro foi usado.

  6. Ao escrever funções de modelo, não há uma resposta clara, porque há algumas desvantagens a considerar que estão além do escopo desta discussão, mas basta dizer que a maioria das funções de modelo ter seus parâmetros por valor ou (const) de referência, no entanto, porque iterador sintaxe é semelhante à dos ponteiros (asterisco para "dereference"), qualquer função modelo que espera iteradores como argumentos também por padrão aceitar ponteiros, bem como (e não verificar NULL desde o NULL iterator conceito tem uma sintaxe diferente).

http://www.cplusplus.com/articles/z6vU7k9E/

O que eu tomar a partir disso é que a principal diferença entre a escolha de usar um parâmetro de ponteiro ou referência é se NULL é um valor aceitável. É isso.

Se o valor for entrada, saída, modificável etc. deve estar na documentação / comentários sobre a função, depois de tudo.

Os esclarecimentos para as mensagens anteriores:


As referências são não a garantia de obter um ponteiro não nulo. (Embora, muitas vezes, tratá-los como tal.)

Enquanto horrifically código ruim, como em levá-lo para fora atrás do woodshed mau código, o seguinte irá compilar e executar: (. Pelo menos sob o meu compilador)

bool test( int & a)
{
  return (&a) == (int *) NULL;
}

int
main()
{
  int * i = (int *)NULL;
  cout << ( test(*i) ) << endl;
};

A verdadeira questão que tenho com referências mentiras com outros programadores, doravante denominado IDIOTAS , que alocar no construtor, deallocate no processo de destruição, e deixar de fornecer um construtor de cópia ou operador = ().

De repente, há um mundo de diferença entre o foo (bar BAR) e foo (BAR & bar) . (A operação automática cópia bit a bit é invocado. Desalocação no destruidor é invocado duas vezes.)

Felizmente modernos compiladores vai pegar esta dupla deallocation do mesmo ponteiro. 15 anos atrás, eles não fizeram. (Sob gcc / g ++, use setenv MALLOC_CHECK_ 0 para revisitar as velhas formas.) Resultante, sob o DEC Unix, na mesma memória sendo alocados a dois objetos diferentes. Muita diversão depuração lá ...


Mais praticamente:

  • Referências esconder que você está mudando os dados armazenados em outro lugar.
  • É fácil confundir uma referência a um objeto copiado.
  • Ponteiros tornar óbvio!

Não é verdade. Internamente, passagem por referência é efectuada por essencialmente passando o endereço do objecto referenciado. Então, realmente não há nenhum ganhos de eficiência a ser tido passando um ponteiro.

Passar por referência tem um benefício, no entanto. Você está garantido para ter uma instância de qualquer objeto / tipo que está sendo passado. Se você passar em um ponteiro, então você corre o risco de receber um ponteiro NULL. Ao usar passagem por referência, você está empurrando um implícito NULL-check-up um nível para o chamador de sua função.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top