Main Content

AUTOSAR C++14 Rule A18-9-3

The std::move shall not be used on objects declared const or const&

Since R2020a

Description

Rule Definition

The std::move shall not be used on objects declared const or const&.

Rationale

When you use std::move() on an object, it is cast into an rvalue. The compiler then manages the resources in the object by calling the constructor or operator with the closest matching parameter list. If you call std::move() on a const or const& type object, the call returns a const or const& type rvalue. Because move constructors and operators do not take a const type argument, the compiler calls the copy constructor or operator instead of the move constructor or operator. Consider this code snippet where a const object is copied when you might expect a move after a call to std::move().

class string{
	//...
public:
	string(const string& rhs);// copy contructor
	string(string&& rhs);     //move constructor
};

void print(string text) {
	cout<<text;
	//...
}

int main(){
	int const message = "Error";
	//..
	print(std::move(message))// the copy constructor is called
}
The return type of std::move(message) is the rvalue const string&&. Between the move and copy constructors of class string, only the copy constructor accepts const type argument. The compiler calls the copy constructor and copies the resources of message into text.

Because std::move() does not move a const or const& type object, avoid using std::move() on const or const& objects. If you intend to move resources from an object, do not declare it as const or const&.

Polyspace Implementation

Polyspace® flags use of std::move() on:

  • Objects that are declared const or const&.

  • Objects that are cast to const or const&.

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

expand all

#include <cstdint>
#include <utility>
class A
{
	// Implementation
};
void F1(const int32_t &is_const, int32_t &is_non_const)
{
	const A a1{};
	int32_t target = 0;
	A a2 = a1;              // Compliant
	A a3 = std::move(a1);   // Noncompliant
	
	target = 
	std::move((const int32_t &)is_non_const);// Noncompliant
	target = 
	std::move(static_cast<const int32_t &>(is_non_const));// Noncompliant 
	target = 
	std::move(const_cast<int32_t &>(is_const));// Compliant
}
int main(){
	//...
}

  • Polyspace flags the use of std::move() with const object a1. The compiler calls the copy constructor to copy a1 to a3. You might expect the compiler to call the move constructor.

  • Polyspace also flags the use of std::move() with the object is_non_const when it is cast to const. After the casting, the compiler calls the copy constructor to copy is_non_const to target. You might expect the compiler to call the move constructor.

  • Polyspace does not flag the use of std::move()with the non-const object that results from casting the const object is_const into a non-const type by using const_cast. After casting, is_const is no longer a const object. The compiler calls the move constructor.

Check Information

Group: Language support library
Category: Required, Automated

Version History

Introduced in R2020a