AUTOSAR C++14 Rule A20-8-5

std::make_unique должны использоваться для построения объектов, принадлежащих std::unique_ptr

Описание

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

std::make_unique должны использоваться для построения объектов, принадлежащих std::unique_ptr.

Объяснение

Вместо выделения памяти при помощи new оператор и преобразование получившегося необработанного указателя в std::unique_ptr объект, для образца:

class numberClass {
   public:
     numberClass(int n): number(n){}
   private: 
     int number;
}
int aNumber=1; 
std::unique_ptr<numberClass> numberPtr (new numberClass(aNumber)); 
Создайте std::unique_ptr объект непосредственно с использованием std::make_unique функция. Для образца:
auto numberPtr = std::make_unique<numberClass>(aNumber);

Использование std::make_unique является предпочтительным, потому что:

  • Создание std::unique_ptr объект, использующий std::make_unique является безопасным для исключений. В противном случае может возникнуть исключение между динамическим выделением памяти со new оператор и последующее преобразование, приводящее к утечке памяти. Исключение вызывает утечку памяти только в определенных контекстах, например, когда std::unique_ptr объект создается в аргументе функции с мультипараметрами, и другая оценка аргумента функции выдает исключение.

  • Можно использовать более краткий синтаксис. Вы не должны повторять тип данных объекта, который динамически распределяется.

Реализация Polyspace

Шашка помечает создание std::unique_ptr объект (или boost::unique_ptr объект) от необработанного указателя, возвращенного new оператор.

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

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

Примеры

расширить все

#include <cstdint>
#include <string>

class Record {
    public:
       Record(std::string aName, std::string someInfo): name(aName), info(someInfo){       
       }
    private:
       std::string name;
       std::string info;
};

void addRecordToDataBase(std::unique_ptr<Record> aRecord, bool dataBaseIsFull);
bool checkDataBase(void); //Checks if database can accept more entries

void createRecord() {
    std::unique_ptr<Record> recordPtr1 (new Record("John", "Mechanic, New York")); //Noncompliant
    auto recordPtr2 = std::make_unique<Record>("Tom", "Plumber, Boston"); //Compliant
    
    addRecordToDataBase(std::unique_ptr<Record>(new Record("John", "Mechanic, New York")), checkDataBase()); //Noncompliant
    addRecordToDataBase(std::make_unique<Record>("Tom", "Plumber, Boston"), checkDataBase()); //Compliant
}

В этом примере правило нарушается всякий раз, когда new оператор возвращает необработанный указатель, и последующее преобразование создает std::unique_ptr объект из необработанного указателя.

При первом вызове addRecordToDatabaseможет происходить следующая последовательность событий (до C++ 17):

  • Оценка первого аргумента. The new оператор динамически выделяет память для Record объект.

  • Вторая оценка аргумента. Функция checkDataBase вызывается.

  • Продолжение оценки первого аргумента. Необработанный указатель, полученный из new оператор преобразуется в std::unique_ptr объект.

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

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

Группа: Библиотека общих утилит
Категория: Необходимый, Автоматизированный
Введенный в R2020b