Ir para o conteúdo

Ú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.

https://abseil.io/tips/188

Tópicos relacionados

Comentários