Main Content

AUTOSAR C++14 Rule A12-0-1

If a class declares a copy or move operation, or a destructor, either via "=default", "=delete", or via a user-provided declaration, then all others of these five special member functions shall be declared as well

Since R2020a

Description

Rule Definition

If a class declares a copy or move operation, or a destructor, either via "=default", "=delete", or via a user-provided declaration, then all others of these five special member functions shall be declared as well.

Rationale

These special member functions are called for copy or move operations:

  • Copy constructor

  • Copy assignment operator

  • Move constructor

  • Move assignment operator

  • Destructor

If you do not explicitly declare any of these functions, the compiler defines them implicitly. This implicit definition implements shallow copying of objects and can cause errors. If you need to explicitly declare any of the special member functions, you must declare all of them. For instance, suppose you want to copy an object that contains a raw pointer to a dynamically allocated memory. The implicit copy constructor shallow-copies the object, after which the original pointer and the copied pointer point to the same memory. If one of the objects is destroyed, the allocated memory is deallocated, leaving a dangling pointer in the other object. Accessing the dangling pointer can cause segmentation errors. Because all the special member functions are closely related, the implicit implementation of the other functions can lead to similar errors. To manage the lifecycle of the dynamically allocated resource, explicitly declare all five of the special member functions (Rule of Five). Alternatively, you can use objects where memory management is correctly implemented in the implicit definition of the special member functions and explicitly declare none of them (Rule of Zero).

When you explicitly declare some but not all of the special member functions, the compiler can prevent the use of the undeclared special member functions. For example, if you explicitly declare only the copy constructor or destructor functions of a class, the compiler no longer defines the move constructor and move assignment operator implicitly. The class becomes a copy-only class, perhaps inadvertently. Conversely, if you explicitly declare only the move constructor and move assignment operator, the compiler disables the copy constructor and copy assignment operator by defining them as deleted. The class becomes a move-only class, which might not have been your intention. To avoid such unwanted effects, either follow the Rule of Five or follow the Rule of Zero.

The constructor of a class is not part of this rule.

Polyspace Implementation

Polyspace® flags classes that explicitly declare some but not all of the five special member functions. Note that the move constructor and move assignment operators were introduced in C++11. Polyspace does not make any exception for older codes.

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

This example demonstrates the Polyspace implementation of AUTOSAR rule A12-0-1.

// Class rendered copy-only, perhaps inadvertently
class A               // Noncompliant.
{
    public:
      ~A()
      {
        // ...
      }

    private:
      // Member data ...
};


//Class rendered move-only, perhaps inadvertently
class B          // Noncompliant
{
   public:
		B(B&&) = default;
		B& operator=(B&&) = default; 
    private:
      // Member data ...
	
};
template<typename T>
class BaseT              // Compliant - rule of five.
{
  public:
    BaseT(BaseT const&) = delete;               
    BaseT(BaseT&&) = delete;                    
    virtual ~BaseT() = default;                 
    BaseT& operator=(BaseT const&) = delete;    
    BaseT& operator=(BaseT&&) = delete;         
    protected:
    BaseT() = default;   
};

template<typename T>
class SimpleT           // Compliant - rule of zero.
{
  public:
    SimpleT(T t): t_(t)
    {

    }

  private:
    T t_;
};

main()
{
	//..	
}

The class A declares only its destructor, which makes this class copy-only because the compiler no longer defines the move constructor and move assignment operator. The class B declares the move constructor and the move assignment operator, which makes this class move-only because the compiler disables the copy constructors and copy assignment operators. It is not clear whether these effects are deliberate. Polyspace flags these declarations and indicates which special member functions are missing. The class BaseT is compliant with this rule because all five of the special member functions are declared. Similarly, SimpleT is compliant because it declares none of the special member functions and relies on their implicit definition.

Check Information

Group: Special member functions
Category: Required, Automated

Version History

Introduced in R2020a