AUTOSAR C++14 Rule A8-4-12
A std::unique_ptr shall be passed to a function as: (1) a copy to express the function assumes ownership (2) an lvalue reference to express that the function replaces the managed object.
Since R2022b
Description
Rule Definition
A std::unique_ptr shall be passed to a function as: (1) a copy to express the function assumes ownership (2) an lvalue reference to express that the function replaces the managed object.
Rationale
You use an std::unique_ptr
smart pointer to indicate that only one
smart pointer owns the managed 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::unique_ptr
smart pointer to a function in one of these ways:
If you expect the function to take ownership of the managed object, pass the smart pointer by value. For instance, the
std::unique_ptr
argument of the caller in this code is moved-from and ownership of theint
object is transferred to an implicitly constructedstd::unique_ptr
smart pointer, which is then passed to the functionfunc()
.void func(std::unique_ptr<int>) {} void otherFunc() { auto smartPtr = make_unique<int>(1); func(std::move(smartPtr)); //caller }
If you expect the function to replace the object that the smart pointer manages, pass the smart pointer as an lvalue reference. For instance, you might replace the managed object by calling the assignment operator or the
reset()
smart pointer member function. For example,uniquePtr
is reset insidefunc()
and no longer manages theint
object in this code.If you do not intend to replace the managed object, pass an lvalue reference to the managed object itself.void func(std::unique_ptr<int>& smartPtr) { smartPtr.reset(); } void otherFunc { auto uniquePtr = make_unique<int>(1); func(std::move(uniquePtr); //caller }
You cannot move or reset a const
-qualified lvalue
reference to an std::unique_ptr
smart pointer. If you do not intend to
modify the managed object, pass a const
-qualified lvalue reference to the
managed object instead.
There is no violation of this rule if you pass an rvalue reference to an
std::unique_ptr
smart pointer and the reference is moved into a
different std::unique_ptr
smart pointer inside the function. For
instance, rvalueRefPtr
is passed by rvalue reference to an
std::unique_ptr
smart pointer and then moved into a different smart
pointer std::unique_ptr
newPtr
.
void func(std::unique_ptr<int>&& rvalueRefPtr) { std::unique_ptr<int> newPtr(std::move(rvalueRefPtr)); }
Polyspace Implementation
Polyspace® the use of a parameter passed as an lvalue reference to
std::unique_ptr
if that parameter is not reset.
Polyspace considers the parameter reset in these cases:
The parameter is used as the destination of a move assignment.
The parameter is moved-from through a call to
std::move
.The parameter is used as the argument of
std::unique_ptr
member functionsreset()
,swap()
, orrelease()
.The parameter is used as the argument of any function that takes a non-
const
qualified lvalue reference to anstd::unique_ptr
smart pointer, regardless of the implementation of the callee.
Polyspace also reports the use of const
-qualified lvalue references
to an std::unique_ptr
smart pointer because you cannot modify the pointer
and transfer ownership of the managed object.
Polyspace does not report the use of smart pointers as parameter types in these cases:
The pointer is used as a parameter of a template function. The parameter type of template functions depends on the instantiation of the function and a fix is not always possible at the template design level. For instance, Polyspace does not report the use of unique pointer
ptr
as parameter 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_unique<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 instance, Polyspace does not report a violation when you use an lvalue reference to unique pointer
ptr
as a parameter offunc()
because it is captured by a lambda function inside the body offunc()
. Polyspace reports the use of 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::unique_ptr<S>& ptr) { // no defect is detected on 'ptr' auto lambdaF = [&ptr0 = ptr] // 'ptr' is captured (by reference) (std::unique_ptr<S> up1) // Non-compliant { // lifetime of 'up1' not affected // ... }; auto b = std::make_unique<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