Use of new or make_unique instead of more efficient make_shared

Использование new или make_unique для инициализации или сброса shared_ptr приводит к дополнительному выделению памяти

Описание

Этот дефект возникает, когда вы используете:

  • new или make_unique для инициализации shared_ptr образец. Для примера:

    std::shared_ptr<T> p1(new T());
    std::shared_ptr<T> p2(make_unique<T>());

  • new для сброса shared_ptr образец. Для примера:

    std::shared_ptr<T> p1;
    //...
    p1.reset(new T);

Вы используете shared_ptr образцы, когда необходимо, чтобы несколько смарт-указателей имели один и тот же объект и управляли им. Образцы также совместно используют блок управления, который содержит количество образцов, которые владеют управляемым объектом.

Polyspace® не помечает использование new для инициализации shared_ptr образец в частных или защищенных конструкторах. Для примера не возникает дефект при использовании new в этом фрагменте кода:

class PrivateCTor
{
public:
    static std::shared_ptr<PrivateCTor> makeOne()
    {
        return std::shared_ptr<PrivateCTor>(new PrivateCTor);
    }
private:
    PrivateCTor();
};

Риск

Когда вы используете new или make_unique для инициализации shared_ptr например, дополнительная операция выделения создает устройство хранения данных для блока управления. Адрес дополнительного выделения может находиться на другой странице памяти или вне кэша данных по сравнению с адресом управляемого объекта.

Зафиксировать

Использование std::make_shared для инициализации shared_ptr образец. Функция выполняет одну операцию выделения с достаточным объемом памяти для хранения управляемого объекта и блока управления.

Эффективность улучшения могут варьироваться в зависимости от используемого компилятора, реализации библиотеки и окружения.

Примеры

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

#include <memory>
#include <string>

struct Profile {
    virtual ~Profile() = default;
};

struct Player : public Profile {
    std::string name;
    std::int8_t rank;

    Player();
    Player(const std::string& name_, const std::int8_t& rank_) :
        name{ name_ }, rank{ rank_ } {}
};

void func()
{

    std::shared_ptr<Player> player1(new Player("Serena Williams", 1));
    std::shared_ptr<Player> top_rank(player1);

}

В этом примере Polyspace помечает использование new для инициализации player1. Программа выполняет дополнительную операцию выделения для блока управления, который содержит счетчик всех образцов shared_ptr которые владеют управляемым Player объект.

Коррекция - Использование std::make_shared Для инициализации shared_ptr

Одной из возможных коррекций является использование std::make_shared для инициализации player1.

#include <memory>
#include <string>

struct Profile {
    virtual ~Profile() = default;
};

struct Player : public Profile {
    std::string name;
    std::int8_t rank;

    Player();
    Player(const std::string& name_, const std::int8_t& rank_) :
        name{ name_ }, rank{ rank_ } {}
};

void func()
{

    auto player1 = std::make_shared<Player>("Serena Williams", 1);
    std::shared_ptr<Player> top_rank(player1);

} 

Информация о результатах

Группа: Эффективность
Язык: C++
По умолчанию: Off
Синтаксис командной строки : MISSING_MAKE_SHARED
Влияние: Низкое
Введенный в R2021a