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