exponenta event banner

Правило AUTOSAR C++ 14 A20-8-6

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

Описание

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

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

Объяснение

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

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

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

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

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

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

Внедрение Polyspace

Средство проверки помечает создание std::shared_ptr объект (или boost::shared_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::shared_ptr<Record> aRecord, bool dataBaseIsFull);
bool checkDataBase(void); //Checks if database can accept more entries

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

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

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

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

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

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

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

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

Группа: Библиотека общих утилит
Категория: Обязательно, Автоматизировано
Представлен в R2020b