Rule A8-4-13 (required, design, automated)
A std::shared_ptr shall be passed to a function as: (1) a copy to express the function shares ownership (2) an lvalue reference to express that the function replaces the managed object (3) a const lvalue reference to express that the function retains a reference count.
Rationale
Passing a std::shared_ptr by value (1) is clear and makes ownership sharing explicit. Passing an lvalue reference (2) to std::shared_ptr is suggested to be used if a called function replaces the managed object on at least one code path, e.g. call assignment operator or reset method. Otherwise, it is recommended to pass an lvalue reference to the underlying object instead, see A8-4-11, A8-4-10. Functions that take a const lvalue reference (3) to std::shared_ptr as a parameter are supposed to copy it to another std::shared_ptr on at least one code path, otherwise the parameter should be passed by a const lvalue reference to the underlying object instead, see A8-4-11, A8-4-10.
Example
// $Id: A8-4-13.cpp 308795 2018-02-23 09:27:03Z michal.szczepankiewicz $
#include <memory>
#include <iostream>
//compliant, explicit ownership sharing
void Value(std::shared_ptr<int> v) { }
//compliant, replaces the managed object
void Lv1(std::shared_ptr<int>& v)
{
v.reset();
}
//non-compliant, does not replace the managed object
//shall be passed by int& so that API that does not
//extend lifetime of an object is not polluted
//with smart pointers
void Lv2(std::shared_ptr<int>& v)
{
++(*v);
}
//compliant, shared_ptr copied in the called function
void Clv1(const std::shared_ptr<int>& v)
{
Value(v);
}
//non-compliant, const lvalue reference not copied
//to a shared_ptr object on any code path
//shall be passed by const int&
void Clv2(const std::shared_ptr<int>& v)
{
std::cout << *v << std::endl;
}
//non-compliant
void Rv1(std::shared_ptr<int>&& r) {}
See also
C++ Core Guidelines [11]: R.34: Take a shared_ptr