Last updated:2026-10-12
C++ Smart Pointers as Function Parameters¶
C++那些事: When Smart Pointers Should Be Function Parameters¶
We often see some functions that take smart pointers as parameters, while others take raw pointers. Which one should you use, and what are the rules for deciding?
This section uses tips from abseil to explain.
Take the following code — what is wrong with it?
bool CanYouPetTheDog(const std::shared_ptr<Dog>& dog,
absl::Duration min_delay) {
return dog->GetLastPetTime() + min_delay < absl::Now();
}
The CanYouPetTheDog function does not affect the ownership of its dog parameter, yet its signature requires it to be stored in a std::shared_ptr. This creates an unnecessary dependency on a particular ownership model, even though the function itself does not need one. This dependency prevents callers from using other models, such as std::unique_ptr or objects constructed on the stack.
Use Pointers/References¶
Use references or pointers when ownership is not affected. By using references/pointers, we remove the dependency on a particular ownership model and allow our function to work with any object of type Dog.
bool CanYouPetTheDog(const Dog& dog, absl::Duration min_delay) {
return dog.GetLastPetTime() + min_delay < absl::Now();
}
With this definition, the function can be called regardless of the caller's ownership model:
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)) { ... }
If the function modifies the value being passed, pass a mutable reference or a raw pointer, using the same approach as above.
Use Smart Pointers¶
Use a smart pointer when the function modifies ownership. The code below provides several overloads for different smart pointer parameters. The first overload assumes ownership of the passed object; the second adds a shared reference to the passed object. Which of these operations applies depends on how the caller wants to handle ownership of the Dog. Ownership of a Dog that lives on the stack cannot be taken, because ownership cannot be taken away from the stack.
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_;
...
};
Summary¶
If ownership is not being transferred or modified, you should avoid taking smart pointers as function parameters.
Related Topics¶
- C++ Pure Virtual Functions and Abstract Classes | C++那些事
- C++ assert | C++那些事
- C++ Bit Fields | C++那些事
- Implementing C++ Polymorphism in C | C++那些事
- C++ const Constants and Qualifiers | C++那些事
- The Complete C++ const Family | C++那些事
- C++ Dereference Operator * | C++那些事
- C++ Initialization and Assignment | C++那些事
- Ways to Return Multiple Values in C++ | C++那些事
- C++ mutable Keyword | C++那些事