Main Content

MISRA C++:2023 Rule 15.0.1

Special member functions shall be provided appropriately

Since R2024b

Description

Rule Definition

Special member functions shall be provided appropriately. 1

Rationale

Special member functions can be provided by the user or implicitly provided by the compiler. It is not always clear which user-declared special member function suppresses which implicitly provided special member function. This rule clarifies which special member functions need to be user-provided. The rule imposes these requirements:

  • Avoid declaring any of the special member functions, unless necessary. This requirement eliminates the need to needlessly mimicking the compiler provided special member functions.

  • Classes must fall into one of these categories: unmovable, move only, and copy enabled. This table summarizes the copyability and movability of these categories:

    CategoryMove ConstructibleMove AssignableCopy ConstructibleCopy Assignable
    UnmovableNoNoNoNo
    Move onlyYesOptionalNoNo
    Copy enabledYesOptionalYesOptional

    This requirement enforces that copy-constructible classes are also move constructible.

  • If a class has nondefault, user-provided or customized copy or move operations, it must also have customized destructor. A customized destructor is a destructor that contains at least one statement that is neither a compound statement nor a null statement. For example:

    struct myClass {
    	int i;
    	myClass(const myClass &other) {
    		i = other.i;
    	}
    
    	myClass(myClass &&other) {
    		i = other.i;
    	}
    
    	~myClass() { //Nondefault user provided destructor
    		i = 0;
    	}
    };
    This requirement enforces correct destruction of classes that handle resource.

  • If a move-only class has a customized destructor, it must also have customized move constructor. If the class is move assignable, it must also have customized move assignment operator. If a copy-enbabled class has a customized destructor, then it must also have customized copy constructor. If the class is copy-assignable, it must also have customized copy assignment operator. This requirement enforces correct copy and move operations for classes that handles resources.

  • If an unmovable class is used as a public base class, then the class must have a public virtual destructor. If a move-only or copy-enabled class is used as a public base class, it must have protected non-virtual destructor. This requirement reduces the risk of slicing. This requirement does not apply to aggregate classes.

Additionally, the rule requires that all out-of-class definitions of special member functions be placed in the same file.

Polyspace Implementation

Polyspace® reports a violation if one or more of these conditions are true:

  • A class does not match any of the copyability and movability combinations described in the preceding table. Such a class cannot be categorized as any of unmovable, move only, or copy enabled.

  • Assignment operators are partially defined.

  • A class is copy constructible but not move constructible.

  • A class is copy or move assignable but not constructible.

  • A class has a customized copy or move operation but no customized destructor.

  • A class has a customized destructor but lacks customized copy or move operations.

  • A nonaggregate unmovable public base class lacks a public virtual destructor.

  • A nonaggregate move-only or copy-enabled public base class lacks a protected non-virtual destructor.

  • An out-of-class definition of a special member function is placed in a different file than the other special member functions.

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

In this example, the class ResourceManager defines a customized move constructor but uses a default destructor. Polyspace reports a violation.

#include <iostream>

class ResourceManager { //Noncompliant
private:
    int* data;

public:
    // Constructor
    explicit ResourceManager(int value) : data(new int(value)) {
        std::cout << "ResourceManager constructed with value: " << value << std::endl;
    }

    // Default Copy Constructor
    ResourceManager(const ResourceManager& other) = default;

    // Move Constructor
    ResourceManager(ResourceManager&& other) noexcept : data(other.data) {
        other.data = nullptr; // Nullify the source pointer
        std::cout << "ResourceManager moved" << std::endl;
    }

    // Default Destructor
    ~ResourceManager() = default;

    // Function to get the value
    int getValue() const {
        return data ? *data : 0; // Return 0 if data is nullptr
    }
};

Check Information

Group: Special member functions
Category: Required

Version History

Introduced in R2024b


1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.

The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:

  • MISRA C:2004

  • MISRA C:2012

  • MISRA C:2023

  • MISRA C++:2008

  • MISRA C++:2023

MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.