AUTOSAR C++14 Rule A8-4-13
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.
Since R2022b
Description
Rule Definition
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
You use an std::shared_ptr
smart pointer to indicate that more than
one smart pointer manages and shares ownership of the same object. A smart pointer manages
the lifetime of a dynamically allocated object and destroys that object when the smart
pointer goes out of scope. Pass an std::shared_ptr
smart pointer to a
function in one of these ways:
If you expect the function to share ownership of the managed object, pass the smart pointer by value. The
std::shared_ptr
reference count is incremented at the start of the function and decremented at the end of the function. For instance,smartPtr
is passed tofunc()
in this code and thatfunc()
shares ownership of the managedint
object until the function ends.void func(std::shared_ptr<int> smartPtr) { //Shared ownership of managed object //smartPtr until end of func }
If you expect the function to replace the object that the smart pointer manages on at least one code path, pass the smart pointer by lvalue reference. For instance, you replace the managed object by calling
operator=
orstd::shared_ptr
member functionreset()
.For example, the lvalue reference parameter of
func()
is reset inside the function and manages a newint
object in this code. The function does not share ownership of the original managed object.If you do not intend to replace the managed object on at least one code path, pass an lvalue reference to the managed object itself (void func(std::shared_ptr<int>& smartPtr) { smartPtr.reset(new int(1)); }
void func(int& obj);
).If you expect that the function might share ownership of the managed object and copy the parameter to another
std::shared_ptr
smart pointer on at least one execution path, pass the smart pointer byconst
lvalue reference. Passing byconst
lvalue reference avoids unnecessary copies on the other execution paths.For instance, the parameter
smartPtr
is not compliant because it is not copied to anotherstd::shared_ptr
on any execution path in this code. If you do not intend to copy the parameter to anotherstd::shared_ptr
smart pointer, pass the parameter byconst
lvalue reference to the managed object itself.#include <iostream> #include <memory> void func(const std::shared_ptr<int>& smartPtr) { //Non-compliant std::cout << *smartPtr << std::endl; }
Polyspace Implementation
Polyspace® reports the use of an std::shared_ptr
smart pointer
parameter passed as an lvalue reference if that parameter is not reset.
Polyspace considers that a parameter is reset in these cases:
The parameter is used as the destination of a copy or move assignment.
The parameter is moved-from through a call to
std::move
.The parameter is used as an argument to
std::shared_ptr
member functionsreset()
orswap()
.The parameter is used as the argument of any function that takes a non-
const
qualified lvalue reference to anstd::shared_ptr
smart pointer, regardless of the implementation of the callee.
Polyspace also reports the use of an std::shared_ptr
pointer
parameter passed as a const
lvalue reference if that parameter is not
copied to another std::shared_ptr
pointer along at least one execution
path.
The parameter is copied to another std::shared_ptr
smart pointer if
it is used as the argument of one of these functions that take a const
lvalue reference to std::shared_ptr
as a parameter:
std::static_pointer_cast
std::dynamic_pointer_cast
std::const_pointer_cast
std::reinterpret_pointer_cast
If you do not intend to copy the parameter to another
shared_ptr
smart pointer, pass a const
lvalue
reference to the managed object instead.
Polyspace does not report the use of smart pointers as parameter types in these cases:
The pointer is passed as an rvalue reference parameter to a function and the pointer is effectively moved-from inside that function.
The pointer is used as a parameter of a template function. The parameter type of a template function depends on the instantiation of that function and a fix is not always possible at the template design level. For instance, Polyspace does not report the use of shared pointer
ptr
in this code.#include <iostream> #include <memory> #include <cassert> template <typename T> double XtimesY(T& ptr) // Use of ptr not flagged { return (ptr->x) * (ptr->y); // ... } struct S { double x; double y; S(double x0, double y0) : x{x0}, y{y0} {} }; void func() { auto a = std::make_shared<S>{100.0, 200.0}; auto b = new S(100.0, 200.0); assert(XtimesY(a) == XtimesY(b)); }
The smart pointer parameter is captured by a lambda function inside the function body. For example, Polyspace does not report the use of the lvalue reference to a shared pointer
ptr
as a parameter offunc()
because a lambda function captures the parameter inside the body offunc()
. Polyspace reports the use of the lambda function parameterup1
because its lifetime is not modified inside the lambda function.#include <memory> struct S { double x; double y; S(double x0, double y0) : x{x0}, y{y0} {} }; void func(std::shared_ptr<S>& ptr) { // no defect is detected on 'ptr' auto lambdaF = [&ptr0 = ptr] // 'ptr' is captured (by reference) (std::shared<S> up1) // Non-compliant { // lifetime of 'up1' not affected // ... }; auto b = std::make_shared<S>(100.0, 200.0); lambdaF(std::move(b)); }
Troubleshooting
If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.
Examples
Check Information
Group: Declarators |
Category: Required, Automated |
Version History
Introduced in R2022b