Última atualização:2026-10-12
Ponteiros inteligentes como parâmetros de função em C++¶
C++那些事: quando usar ponteiros inteligentes como parâmetros de função¶
Costumamos ver algumas funções que recebem ponteiros inteligentes como parâmetros e outras que usam ponteiros brutos: qual usar afinal? E qual é o princípio a seguir?
Esta seção usa as dicas (tips) da abseil para a explicação.
Como mostrado abaixo: qual é o problema deste código?
bool CanYouPetTheDog(const std::shared_ptr<Dog>& dog,
absl::Duration min_delay) {
return dog->GetLastPetTime() + min_delay < absl::Now();
}
A função CanYouPetTheDog não afeta a propriedade (ownership) do seu parâmetro dog, mas sua assinatura exige que ele seja armazenado em um std::shared_ptr. Isso cria uma dependência desnecessária de um modelo de propriedade específico, embora a função em si não precise dela. Essa dependência impede que o chamador use outros modelos, como std::unique_ptr ou objetos construídos na pilha.
Usar ponteiros/referências¶
Quando a propriedade não é afetada, use referências ou ponteiros. Ao usar referências/ponteiros, eliminamos a dependência de um modelo de propriedade específico e permitimos que nossa função trabalhe com qualquer objeto do tipo Dog.
bool CanYouPetTheDog(const Dog& dog, absl::Duration min_delay) {
return dog.GetLastPetTime() + min_delay < absl::Now();
}
Com a definição acima, a função pode ser chamada independentemente do modelo de propriedade do chamador:
Dog stack_dog;
if (CanYouPetTheDog(stack_dog, delay)) { ... }
auto heap_dog = std::make_unique<Dog>();
if (CanYouPetTheDog(*heap_dog, delay)) { ... }
CustomPetPtr<Dog> custom_dog = CreateDog();
if (CanYouPetTheDog(*custom_dog, delay)) { ... }
Se a função modificar o valor passado, passe uma referência mutável ou um ponteiro bruto, usando o mesmo padrão descrito acima.
Usar ponteiros inteligentes¶
Use ponteiros inteligentes quando a função modifica a propriedade; o código a seguir oferece algumas sobrecargas para diferentes parâmetros de ponteiro inteligente. A primeira sobrecarga assume a propriedade do objeto passado; a segunda adiciona uma referência compartilhada ao objeto passado. Qual das duas operações usar depende de como o chamador trata a propriedade do Dog. Não é possível assumir a propriedade de um Dog localizado na pilha, porque não se pode tirar a propriedade de dentro da pilha.
class Human {
public:
...
void Adopt(std::unique_ptr<Dog> dog) {
pets_.push_back(std::move(dog));
}
void Adopt(std::shared_ptr<Cat> cat) {
pets_.push_back(std::move(cat));
}
private:
std::vector<std::shared_ptr<Pet>> pets_;
...
};
Resumo¶
Se a propriedade não for transferida nem modificada, evite passar ponteiros inteligentes como parâmetros de função.
Tópicos relacionados¶
- Funções virtuais puras e classes abstratas em C++ | C++那些事
- Asserções com assert em C++ | C++那些事
- Bit fields em C++ | C++那些事
- Implementando polimorfismo de C++ em linguagem C | C++那些事
- Constantes e modificadores com const em C++ | C++那些事
- A família completa do const em C++ | C++那些事
- O operador de desreferência * em C++ | C++那些事
- Inicialização e atribuição em C++ | C++那些事
- Formas de retornar múltiplos valores em C++ | C++那些事
- A palavra-chave mutable em C++ | C++那些事