メインコンテンツ

より効率的な make_shared の代わりに、new または make_unique が使用されています

new または make_unique を使用して shared_ptr を初期化またはリセットすると、追加のメモリ割り当てが発生する

R2021a 以降

説明

この欠陥は、以下の場合に発生します。

  • 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 インスタンスを初期化すると、追加の割り当て操作により、制御ブロックのストレージが作成されます。管理対象のオブジェクトのアドレスと比べて、追加割り当てのアドレスは異なるメモリ ページまたはデータ キャッシュの外部にあります。

修正方法

shared_ptr インスタンスを初期化するには、std::make_shared を使用します。この関数は単一の割り当て操作で、管理対象のオブジェクトと制御ブロックを格納するのに十分なメモリを割り当てます。

パフォーマンスの改善の程度は、使用しているコンパイラ、ライブラリ実装、環境によって異なる可能性があります。

すべて展開する

#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 の初期化にフラグを設定します。このプログラムは、制御ブロックに対し追加の割り当て操作を行います。この制御ブロックは、管理対象の Player オブジェクトを所有する shared_ptr のすべてのインスタンスのカウンターを保持します。

修正 — std::make_shared を使用して shared_ptr を初期化

1 つの修正方法として、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++
既定値: オフ
コマンド ライン構文: MISSING_MAKE_SHARED
影響度: Low

バージョン履歴

R2021a で導入