AUTOSAR C++14 Rule A12-0-1

Если класс объявит копию или операцию пересылки или деструктор, или через "=default", "=delete", или через обеспеченное пользователями объявление, то все другие этих пяти специальных функций членства должны быть объявлены также.

Описание

Управляйте определением

Если класс объявит копию или операцию пересылки или деструктор, или через "=default", "=delete", или через обеспеченное пользователями объявление, то все другие этих пяти специальных функций членства должны быть объявлены также.

Объяснение

Эти специальные функции членства называются для копии или операций пересылки:

  • Копирование конструктора

  • Копирование оператора присваивания

  • Перемещение конструктора

  • Перемещение оператора присваивания

  • Деструктор

Если вы явным образом не объявляете ни одной из этих функций, компилятор задает их неявно. Это неявное определение реализует мелкое копирование объектов и может вызвать ошибки. Если необходимо явным образом объявить какую-либо из специальных функций членства, необходимо объявить всех их. Например, предположите, что вы хотите скопировать объект, который содержит необработанный указатель на динамически выделенную память. Неявные мелкие копии конструктора копии объект, после которого исходный указатель и скопированный указатель указывают на ту же память. Если один из объектов уничтожается, выделенная память освобождена, оставив висячий указатель в другом объекте. Доступ к висячему указателю может вызвать ошибки сегментации. Поскольку все специальные функции членства тесно связаны, неявная реализация других функций может привести к подобным ошибкам. Чтобы управлять жизненным циклом динамически выделенного ресурса, явным образом объявите все пять из специальных функций членства (Правило Пять). В качестве альтернативы можно использовать объекты, где управление памятью правильно реализовано в неявном определении специальных функций членства, и явным образом не объявите ни одного из них (Правило Нуля).

Когда вы явным образом объявляете некоторых, но не все специальные функции членства, компилятор может предотвратить использование необъявленных специальных функций членства. Например, если вы явным образом объявляете только конструктора копии или функции деструктора класса, компилятор больше не задает конструктора перемещения и оператор присваивания перемещения неявно. Класс становится классом только для копии, возможно, непреднамеренно. С другой стороны, если вы явным образом объявляете только конструктора перемещения и перемещаете оператор присваивания, компилятор отключает конструктора копии и оператор присваивания копии путем определения их, как удалено. Класс становится классом только для перемещения, который не может быть вашим намерением. Чтобы избежать таких нежелательных эффектов, или следовать Правилу Пять или следуют Правилу Нуля.

Конструктор класса не является частью этого правила.

Реализация Polyspace

Polyspace® отмечает классы, которые явным образом объявляют некоторых, но не все пять специальных функций членства. Обратите внимание на то, что конструктор перемещения и операторы присваивания перемещения были введены на C++ 11. Polyspace не делает исключения для более старых кодов.

Поиск и устранение проблем

Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.

Примеры

развернуть все

Этот пример демонстрирует реализацию Polyspace правила A12-0-1 AUTOSAR.

// 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()
{
	//..	
}

Класс A объявляет только его деструктор, который делает этот класс только для копии, потому что компилятор больше не задает конструктора перемещения и оператор присваивания перемещения. Класс B объявляет конструктора перемещения и оператор присваивания перемещения, который делает этот класс только для перемещения, потому что компилятор отключает конструкторов копии и операторы присваивания копии. Не ясно, являются ли эти эффекты преднамеренными. Polyspace отмечает эти объявления и указывает, какие специальные функции членства отсутствуют. Класс BaseT совместимо с этим правилом, потому что все пять из специальных функций членства объявляются. Точно так же SimpleT совместимо, потому что это не объявляет ни одну из специальных функций членства и использует их неявное определение.

Проверяйте информацию

Группа: Специальные функции членства
Категория: необходимый, автоматизированный
Введенный в R2020a