AUTOSAR C++14 Rule A8-4-11
A smart pointer shall only be used as a parameter type if it expresses lifetime semantics
Since R2022b
Description
Rule Definition
A smart pointer shall only be used as a parameter type if it expresses lifetime semantics.
Rationale
A smart pointer manages the lifetime of a dynamically allocated object and destroys that
object when the smart pointer goes out of scope. When you use a smart pointer as a parameter
type for a function, you restrict that function to callers that use smart pointers, which is
unnecessary if the function does not affect the lifetime of the managed object. In the case
of shared smart pointers such as std::shared_ptr
, your program incurs
additional run-time overhead.
Examples of functions that affect the lifetime of a managed object include:
A function that transfers ownership of the managed object from the
std::unique_ptr
smart pointer parameter to a differentstd::unique_ptr
smart pointer through a move operation.A function that copies the
std::shared_ptr
smart pointer parameter inside the function body, sharing the ownership of the managed object with anotherstd::shared_ptr
smart pointer.
If the function does not affect the lifetime of the managed object, pass the object by reference or as a raw pointer instead.
If that object is managed by a non-local smart pointer, check that both these conditions are true:
The object is not reset or reassigned inside a function that is down the call tree of the called function.
The managed object is not destroyed before it is dereferenced.
For instance, if the object is managed by a non-local shared pointer, make a local copy inside the called function.
The use of a non-owning smart pointer as a parameter type, such as
std::observer_ptr
, is compliant with this rule. See std::experimental::observer_ptr
.
Polyspace Implementation
Polyspace® reports a violation of this rule when you use smart pointers
std::shared_ptr
or std::unique_ptr
as parameter
types in a user-defined function that does not affect the lifetime of those smart pointers
in the function body.
Polyspace considers the lifetime of an std::shared_ptr
smart pointer
parameter affected if, along at least one execution path:
The pointer is copied through a copy constructor or a copy assignment.
The pointer is moved-from through a move constructor or move assignment. This operation involves a call to
std::move
.The pointer is passed as an argument to a function with one of these parameter types:
An
std::shared_ptr<T>
type. In this case the copy constructor is invoked.A
const std::shared<T>&
type. Thisconst
lvalue reference indicates that the function retains a reference count and might make a copy of the pointer.An
std::shared<T>&
type. This lvalue reference indicates that the passed parameter will be modified.
A modifier member function such as
std:shared_ptr::reset
or a modifier non-member function such asstd::shared_ptr::swap
is called on the pointer. For a list of modifier functions, see std::shared_ptr.The pointer is the destination of a copy or move assignment.
const
-qualified std::shared_ptr
smart
pointer parameters cannot be modified.
Polyspace considers the lifetime of an std::unique_ptr
smart pointer
parameter affected if, along at least one execution path:
The pointer is moved-from with a call to
std::move
.The pointer is moved-from through a move constructor or a move assignment.
The pointer is passed as an argument to a function with one of these parameter types:
An
std::unique_ptr<T>
type. In this case, the move constructor is invoked.An
std::unique<T>&
type. This lvalue reference indicates that the function modifies the passed parameter.
A modifier member function such as
std::unique_ptr::reset
or a modifier non-member function such asstd::unique_ptr::swap
is called on the pointer. For a list of modifier functions, see std::unique_ptr.The pointer is the destination of a move assignment.
const
-qualified std::unique_ptr
smart
pointer parameters cannot be moved-from or modified and their lifetimes are not affected.
The lifetime of the passed argument is also not affected in the case of the
const
lvalue reference parameter const
std::unique_ptr<T>&
.
Polyspace does not report a violation of this rule when you use smart pointers as parameter types in these cases:
The pointer is used as a parameter of a template function. The parameter types of a template function depend on the instantiation of the function and a fix is not always possible at the template design level. For instance, the use of the shared pointer
ptr
is not reported as a violation 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 = new S{100.0, 200.0}; auto a_cpy = std::shared_ptr<S>(a); assert(XtimesY(a) == XtimesY(a_cpy)); }
The smart pointer parameter is captured by a
lambda
function inside the function body. For instance, Polyspace does not report a violation when you use the shared pointerptr
as a parameter offunc()
in this code. The parameter is captured by alambda
function inside the body offunc()
. Polyspace reports the use oflambda
function parameterssp1
andup1
as violations because their lifetime is not modified inside thelambda
function.#include <memory> struct S { double x; double y; S(double x0, double y0) : x{x0}, y{y0} {} }; void func(std::unique_ptr<S> ptr) { // no defect is detected on 'ptr' auto lambdaF = [&ptr0 = ptr] // 'ptr' is captured (by reference) (std::shared_ptr<S> sp1, // Non-compliant std::unique_ptr<S> up1) // Non-compliant { // lifetime of 'sp1' and 'up1' not affected // ... }; auto a = std::make_shared<S>(1.0, 2.0); auto b = std::make_unique<S>(100.0, 200.0); lambdaF(a, 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