Qual seria a melhor prática ao atribuir a uma função a variável original para trabalhar:
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
ou:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
IOW: Existe algum motivo para escolher um sobre o outro?
Respostas:
Minha regra de ouro é:
Use ponteiros se desejar fazer a aritmética do ponteiro com eles (por exemplo, incrementar o endereço do ponteiro para percorrer uma matriz) ou se precisar passar um ponteiro NULL.
Use referências caso contrário.
fonte
Base* b = new Derived()
)? Parece um caso que não pode ser tratado sem ponteiros.Realmente acho que você se beneficiará do estabelecimento da seguinte função, chamando diretrizes de codificação:
Como em todos os outros lugares, sempre esteja
const
correto.const
especificador.Somente passe um valor por ponteiro se o valor 0 / NULL for uma entrada válida no contexto atual.
Justificativa 1: Como chamador , você vê que tudo o que você passa deve estar em um estado utilizável.
Fundamentação 2: Conforme chamado , você sabe que tudo o que entra está em um estado utilizável. Portanto, nenhuma verificação NULL ou manipulação de erros precisa ser feita para esse valor.
Razão 3: As razões 1 e 2 serão aplicadas pelo compilador . Sempre pegue erros em tempo de compilação, se puder.
Se um argumento de função for um valor externo, passe-o por referência.
Escolha "passar por valor" sobre "passar por referência de const" apenas se o valor for um POD (estrutura de dados antiga simples ) ou pequeno o suficiente (em memória) ou de outras maneiras barato o suficiente (em tempo) para copiar.
fonte
std::vector<>
.Isso acaba sendo subjetivo. A discussão até agora é útil, mas não acho que haja uma resposta correta ou decisiva para isso. Muito dependerá das diretrizes de estilo e das suas necessidades no momento.
Embora existam alguns recursos diferentes (se algo pode ou não ser NULL) com um ponteiro, a maior diferença prática para um parâmetro de saída é puramente a sintaxe. O Guia de estilo C ++ do Google ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments ), por exemplo, exige apenas ponteiros para os parâmetros de saída e permite apenas referências que são const. O raciocínio é de legibilidade: algo com sintaxe de valor não deve ter um significado semântico de ponteiro. Não estou sugerindo que isso seja necessariamente certo ou errado, mas acho que o ponto aqui é que é uma questão de estilo, não de correção.
fonte
Você deve passar um ponteiro se quiser modificar o valor da variável. Mesmo que tecnicamente passar uma referência ou um ponteiro seja o mesmo, passar um ponteiro no seu caso de uso é mais legível, pois "anuncia" o fato de que o valor será alterado pela função.
fonte
const
ou nãoconst
de referência, mas você pode ver se o parâmetro do passado ala&x
vs.x
e uso essa convenção para codificar se o parâmetro pode ser modificado. (Dito isso, há momentos em que você deseja passar por umconst
ponteiro, então a convenção é apenas uma dica. É possível suspeitar que algo pode ser modificado quando não será, é menos perigoso do que pensar que não será quando será. ....)Se você possui um parâmetro em que pode precisar indicar a ausência de um valor, é prática comum transformar o parâmetro em um valor de ponteiro e passar NULL.
Uma solução melhor na maioria dos casos (de uma perspectiva de segurança) é usar o boost :: opcional . Isso permite que você transmita valores opcionais por referência e também como um valor de retorno.
fonte
Use uma referência quando puder, use um ponteiro quando precisar. Do FAQ do C ++: "Quando devo usar referências e quando devo usar ponteiros?"
fonte
Ponteiros
Um ponteiro que atualmente não aponta para um local válido da memória recebe o valor nulo (que é zero)
O & é um operador unário que retorna o endereço de memória de seu operando.
O operador de desreferenciação (*) é usado para acessar o valor armazenado na variável para a qual o ponteiro aponta.
Referência
Uma referência (&) é como um alias para uma variável existente.
Uma referência (&) é como um ponteiro constante que é automaticamente desreferenciado.
Geralmente é usado para listas de argumentos de função e valores de retorno de função.
Uma referência deve ser inicializada quando é criada.
Depois que uma referência é inicializada para um objeto, ela não pode ser alterada para se referir a outro objeto.
Você não pode ter referências NULL.
Uma referência const pode se referir a uma const int. Isso é feito com uma variável temporária com o valor da const
fonte
Uma referência é um ponteiro implícito. Basicamente, você pode alterar o valor para o qual a referência aponta, mas não pode alterar a referência para apontar para outra coisa. Então, meus 2 centavos é que, se você quiser alterar apenas o valor de um parâmetro, passe-o como referência, mas se precisar alterar o parâmetro para apontar para um objeto diferente, passe-o usando um ponteiro.
fonte
Considere a palavra-chave de saída do C #. O compilador requer que o chamador de um método aplique a palavra-chave out a qualquer argumento de saída, mesmo que ele já saiba se o é. Isso tem como objetivo melhorar a legibilidade. Embora com os IDEs modernos, estou inclinado a pensar que este é um trabalho de destaque de sintaxe (ou semântica).
fonte
Passe por referência const, a menos que haja uma razão pela qual você queira alterar / manter o conteúdo que está passando.
Este será o método mais eficiente na maioria dos casos.
Certifique-se de usar const em cada parâmetro que você não deseja alterar, pois isso não apenas protege você de fazer algo estúpido na função, mas também fornece aos outros usuários o que a função faz com os valores passados. Isso inclui fazer um ponteiro const quando você deseja alterar apenas o que é indicado ...
fonte
Ponteiros:
nullptr
(ouNULL
).&
se o seu tipo não for um ponteiro, tornando explicitamente a modificação do seu objeto.Referências:
&
. Isso às vezes é considerado ruim porque você deve ir para a implementação da função para ver se seu parâmetro foi modificado.fonte
Uma referência é semelhante a um ponteiro, exceto que você não precisa usar um prefixo ∗ para acessar o valor referido pela referência. Além disso, não é possível fazer uma referência para se referir a um objeto diferente após sua inicialização.
As referências são particularmente úteis para especificar argumentos de função.
para obter mais informações, consulte "Um tour pelo C ++" de "Bjarne Stroustrup" (2014) Páginas 11-12
fonte