diferença entre um ponteiro e um parâmetro de referência?

São os mesmos:

int foo(bar* p) { return p->someInt(); } 

e

 int foo(bar& r) { return r.someInt(); } 

Ignore o potencial do ponteiro nulo. Estas duas funções são funcionalmente idênticas, não importa se someInt() é virtual ou se elas são passadas uma bar ou uma subclass de bar ?

Isso faz alguma coisa:

 bar& ref = *ptr_to_bar; 

Referências C ++ não são intencionalmente especificadas no padrão a ser implementado usando pointers. Uma referência é mais como um “sinônimo” para uma variável do que um ponteiro para ela. Esta semântica abre algumas otimizações possíveis para o compilador quando é possível perceber que um ponteiro seria um exagero em algumas situações.

Mais algumas diferenças:

  • Você não pode atribuir NULL a uma referência. Esta é uma diferença crucial e a principal razão pela qual você preferiria uma sobre a outra.
  • Quando você pega o endereço de um ponteiro, você obtém o endereço da variável do ponteiro. Quando você pega o endereço de uma referência, você obtém o endereço da variável que está sendo referida.
  • Você não pode reatribuir uma referência. Uma vez inicializado, aponta para o mesmo object durante toda a sua vida.

Ignorando todo açúcar sintático e possibilidades que podem ser feitas com um e não com o outro e diferença entre pointers e referências explicadas em outras respostas (para outras perguntas) … Sim, esses dois são funcionalmente exatamente iguais! Ambos chamam a function e ambos lidam com funções virtuais igualmente bem.

E não, sua linha não corta. É apenas ligar a referência diretamente ao object apontado por um ponteiro.

Algumas perguntas sobre por que você gostaria de usar uma sobre a outra:

  • Diferença entre ponteiro e referência
  • Há algum benefício de passar pelo ponteiro sobre a referência?
  • Ponteiro vs. Referência

Em vez de tentar propor diferenças, eu o delega para quem deseja saber.

A referência é um ponteiro constante, ou seja, você não pode alterar a referência para se referir a outro object. Se você alterar, o valor do object de referência será alterado.

Por ex:

  int j = 10; int &i = j; int l = 20; i = l; // Now value of j = 20 int *k = &j; k = &l; // Value of j is still 10 

Sim, eles são funcionalmente idênticos. Como uma referência exigirá que você a defina como object antes de usá-la, você não precisará lidar com pointers nulos ou pointers para memory inválida.

Também é importante ver a diferença semântica:

  • Use uma referência quando você realmente passasse o object normal – mas é tão grande que faz mais sentido passar uma referência ao object em vez de fazer uma cópia (se você não estiver modificando o object que está).
  • Use um ponteiro quando você quiser lidar com o endereço de memory em vez de com o object.

Eu não uso o C ++ há muito tempo, então eu nem vou tentar responder a sua pergunta (desculpe); No entanto, Eric Lippert acaba de postar um excelente artigo sobre pointers / referências que eu imaginei que eu apontaria para você.

Não tenho certeza se alguém respondeu sua segunda pergunta escondida na parte inferior sobre o corte … não que não vai causar o corte.

Slicing é quando um object derivado é atribuído (copiado) a um object de class base – a especialização da class derivada é “cortada”. Note que eu disse que o object é copiado, não estamos falando de pointers sendo copiados / atribuídos, mas dos próprios objects.

No seu exemplo, isso não está acontecendo. Você está apenas des-referenciando um ponteiro para um object Bar (resultando assim em um object Bar) sendo usado como o rvalor em uma boot de referência. Não tenho certeza se tenho a terminologia correta …

Como todos os outros mencionaram, na implementação, referências e pointers são basicamente os mesmos. Existem algumas pequenas advertências:

  • Você não pode atribuir NULL a uma referência (isto é, mencionar isso): isso é significativo, já que não há um valor de referência “indefinido” ou “inválido”.

  • Você pode passar uma variável temporária como uma referência const , mas não é legal passar um ponteiro para um temporário.

Por exemplo, tudo bem:

 class Thingy; // assume a constructor Thingy(int,int) void foo(const Thingy &a) { a.DoSomething(); } void bar( ) { foo( Thingy(1,2) ); } 

mas a maioria dos compiladores vai reclamar

 void foo2( Thingy * a); void bar2() { foo( &Thingy(1,2) ); } 
  • Tomando o endereço de uma variável para obter um ponteiro força o compilador a salvá-lo na memory. Atribuir uma referência a uma variável local apenas cria um sinônimo; em alguns casos, isso pode permitir que o compilador mantenha os dados no registro e evite um armazenamento de access de carga . No entanto, isso só se aplica a variables ​​locais – uma vez que algo é passado como um parâmetro por referência, não há como evitar salvá-lo na pilha.
 void foo() { int a = 5; // this may be slightly more efficient int &b = a; printf( "%d", ++b ); // than this int *c = &a; printf( "%d", ++(*c) ); } 
  • Da mesma forma, a palavra-chave __restrito não pode ser aplicada a referências, apenas a pointers.

  • Você não pode fazer aritmética de pointers com referências, portanto, se você tiver um ponteiro em uma matriz, o próximo elemento na matriz pode ser obtido através de p + 1, uma referência só aponta para uma coisa em sua vida inteira.

As funções obviamente não são “as mesmas”, mas no que diz respeito ao comportamento virtual, elas se comportarão de maneira semelhante. Em relação ao fatiamento, isso só acontece quando você lida com valores, não referências ou pointers.