Quando passar por referência e quando passar pelo ponteiro em C ++?

Situações comuns:

  1. Passando std :: string para uma function foo (std :: string *) ou foo (std :: string &);
  2. Passando tr1 :: shared_ptr para uma function foo (tr1 :: shared_ptr * ptr) ou foo (tr1 :: shared_ptr & ptr);

Em geral, o que é uma boa prática. Eu sempre fico confuso. No começo, passar tudo como referências parece consistente, porém não é possível passar em Literais como referências ou NULLs como referências.

Da mesma forma, ter tudo como pointers parece bom, mas depois disso eu tenho que me preocupar que os pointers possam estar apontando para NULL e verificar essas condições no início dessa function.

Você acha que o seguinte trecho é bom?

#include  #include  #include  #include  #include  #include  using namespace std; using namespace std::tr1; int main(){ map<string, shared_ptr<vector > > adjacencyMap; vector* myFriends = new vector(); myFriends->push_back(string("a")); myFriends->push_back(string("v")); myFriends->push_back(string("g")); adjacencyMap["s"] = shared_ptr<vector >(myFriends); return 0; } 

Graças ajay

Referências são mais fáceis de acertar.

Seu problema com literais é que você não está usando referências constantes? Você não pode ligar um temporário (produzido por um literal) a uma referência não-const, porque não faz sentido alterar um. Você pode vincular um a uma referência const.

Em particular, ao passar um argumento para uma function, e a function não vai alterá-lo, e não é um tipo interno, passe por referência const. Ele funciona da mesma maneira que passar por valor, exceto que não requer uma chamada de construtor de cópia.

Os pointers são úteis porque têm um valor inválido garantido que você pode testar. Às vezes isso é irrelevante e, às vezes, é muito importante. Claro, você geralmente não pode passar um literal por ponteiro, a menos que (no caso de uma literal de string) já esteja.

Alguns padrões de codificação dizem que nada deve ser passado por referência não const, uma vez que não fornece nenhuma indicação no ponto de chamada de que o argumento possa ser alterado pela function. Nesse caso, você será obrigado a passar pelo ponteiro. Eu não sou a favor disso, particularmente porque as ferramentas de programação facilitam e facilitam a obtenção da assinatura da function, assim você pode ver se uma function pode mudar um argumento. No entanto, quando se trabalha em um grupo ou para uma empresa, a consistência de estilo é mais importante do que qualquer elemento de estilo individual.

Uma boa regra prática: “Use referências quando puder e indique quando for necessário”.

Eu realmente não entendo porque você teve todo esse problema:

 std::map < std::string, std::vector > adjacencyMap; std::vector& sFriends = adjacencyMap["s"]; sFriends.push_back("a"); sFriends.push_back("v"); sFriends.push_back("g"); 

Por que você se intromete com shared_ptr aqui? A situação certamente não exige!

Em meu trabalho anterior, tínhamos a regra de que referências simples praticamente nunca eram usadas. Em vez disso, concordamos em:

  • passar por valor (para barato copiar objects, primitivos, pequenos valores, std :: string , muito pequenos ou refinados)
  • passar por referência const (para access somente leitura a objects grandes)
  • passar pelo ponteiro se precisar de access de leitura / gravação

Se todos seguirem essas regras, você pode assumir que os parâmetros passados ​​para as funções não são modificados, a menos que seu endereço tenha sido escolhido. Funcionou para nós.

Provavelmente não é uma resposta para a pergunta. Apenas BEIJE

 int main() { multimap adjacencyMap; adjacencyMap.insert(std::make_pair("s", "a")); adjacencyMap.insert(std::make_pair("s", "v")); adjacencyMap.insert(std::make_pair("s", "g")); return 0; } 

Você pode navegar em http://www.cplusplus.com/forum/beginner/3958/ para obter algumas informações. Também é útil: http://www.velocityreviews.com/forums/t284603-pointers-vs-references-a-question-on-style.html

Eu acho que não há resposta “certa”. Você precisa ponderar os prós e contras de cada abordagem, levando em consideração o contexto específico do seu projeto.

Eu pessoalmente prefiro referências, mas eu recomendo de qualquer maneira ler esses posts e refletir sobre isso.

Como regra geral, sempre tente passar parâmetros por referência a const. Passar pointers pode levar a problemas de propriedade, bem como a várias outras possibilidades de erros sutis.

Qual é o objective do NULL? Para indicar um ponteiro / object inválido. Se você vai passar objects inválidos para uma function, então tudo o que você precisa fazer é ter um método para verificar a validade de um object. Como em:

 void myfunc(const obj& myobj) { if(myobj.valid()) // DO SOMETHING } 

Tipos primitivos que você normalmente deseja passar por valor de qualquer maneira, já que há pouca sobrecarga. E é quando você usa literais a maior parte do tempo de qualquer maneira. Para seqüências de caracteres, você deve tentar usar std::string e ficar longe de strings const char* estilo C, tanto quanto possível. Claro que se você tiver que usar strings C, então você não tem escolha a não ser usar pointers, mas todas as referências devem ser o caminho a seguir.

Ah, e para ser verdadeiramente seguro, tente evitar isso:

 vector* myFriends = new vector(); ... adjacencyMap["s"] = shared_ptr >(myFriends); 

Em vez disso:

 shared_ptr > myFriends(new vector()); 

Olhe para RAII e segurança de exceção por que este é o método preferido.

eu preferiria

  map > > adjacencyMap; shared_ptr > myFriends(new vector()); myFriends->push_back(string("a")); myFriends->push_back(string("v")); myFriends->push_back(string("g")); adjacencyMap["s"] = myFriends; return 0; 

já que isso garante que seu manuseio de var local seja isento de exceções.

Eu realmente não vejo como isso resolve seu q, que era sobre os méritos de ref vs ptr, no entanto. Em ambos os exemplos citados, eu esperaria usar o segundo (ref) formulário.