exponenta event banner

Правило AUTOSAR C++ 14 A12-0-1

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

Описание

Определение правила

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

Объяснение

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

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

  • Копировать оператор назначения

  • Конструктор перемещения

  • Оператор назначения перемещения

  • Деструктор

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

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

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

Внедрение Polyspace

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

Поиск неисправностей

Если вы ожидаете нарушения правила, но не видите его, обратитесь к разделу Нарушения стандартов кодирования не отображаются.

Примеры

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

В этом примере показана реализация правила A12-0-1 AUTOSAR в Polyspace.

// 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