AUTOSAR C++14 Rule 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):

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

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

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

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

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

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