次の方法で共有


方法: unique_ptr インスタンスを作成して使用する

unique_ptr は、ポインターを共有しません。 別の unique_ptr にコピーすることも、値によって関数に渡すことも、コピーの作成が必要な C++ 標準ライブラリのアルゴリズムで使用することもできません。 unique_ptr ができるのは移動だけです。 この場合、メモリ リソースの所有権は別の unique_ptr に移動し、元の unique_ptr はそれ以降、所有権を失います。 複数の所有者がオブジェクトを所有するとプログラム ロジックが複雑になるため、所有者を 1 人に制限することをお勧めします。 したがって、プレーンな C++ オブジェクト用のスマート ポインターが必要な場合は unique_ptr を使用し、unique_ptr を構成する場合は make_unique ヘルパー関数を使用します。

次の図では、2 つの unique_ptr のインスタンス間での所有権の移転を示します。

Diagram that shows moving the ownership of a unique pointer.

unique_ptr は、C++ 標準ライブラリの <memory> ヘッダーで定義されています。 これは、生ポインターと同じくらい効率的で、C++ 標準ライブラリのコンテナーで使用できます。 C++ 標準ライブラリのコンテナーに unique_ptr インスタンスを追加すると、unique_ptr の移動コンストラクターによってコピー操作が不要になるため効率的です。

例 1

次の例では、unique_ptr インスタンスを作成し、関数間で渡す方法を示します。

unique_ptr<Song> SongFactory(const std::wstring& artist, const std::wstring& title)
{
    // Implicit move operation into the variable that stores the result.
    return make_unique<Song>(artist, title);
}

void MakeSongs()
{
    // Create a new unique_ptr with a new object.
    auto song = make_unique<Song>(L"Mr. Children", L"Namonaki Uta");

    // Use the unique_ptr.
    vector<wstring> titles = { song->title };

    // Move raw pointer from one unique_ptr to another.
    unique_ptr<Song> song2 = std::move(song);

    // Obtain unique_ptr from function that returns by value.
    auto song3 = SongFactory(L"Michael Jackson", L"Beat It");
}

これらの例は、unique_ptr の基本的な機能として、移動はできるが、コピーはできないことを示しています。 「移動」は unique_ptr に所有権を移転し、元の unique_ptr をリセットします。

例 2

次の例では、unique_ptr インスタンスを作成し、ベクター内で使用する方法を示します。

void SongVector()
{
    vector<unique_ptr<Song>> songs;
    
    // Create a few new unique_ptr<Song> instances
    // and add them to vector using implicit move semantics.
    songs.push_back(make_unique<Song>(L"B'z", L"Juice")); 
    songs.push_back(make_unique<Song>(L"Namie Amuro", L"Funky Town")); 
    songs.push_back(make_unique<Song>(L"Kome Kome Club", L"Kimi ga Iru Dake de")); 
    songs.push_back(make_unique<Song>(L"Ayumi Hamasaki", L"Poker Face"));

    // Pass by const reference when possible to avoid copying.
    for (const auto& song : songs)
    {
        wcout << L"Artist: " << song->artist << L"   Title: " << song->title << endl; 
    }    
}

ループの範囲で、unique_ptr が参照渡しされることに注意してください。 ここで値によって渡そうとすると、unique_ptr コピー コンストラクターが削除されるため、コンパイラによってエラーがスローされます。

例 3

次の例では、クラス メンバーである unique_ptr を初期化する方法を示しています。


class MyClass
{
private:
    // MyClass owns the unique_ptr.
    unique_ptr<ClassFactory> factory;
public:

    // Initialize by using make_unique with ClassFactory default constructor.
    MyClass() : factory (make_unique<ClassFactory>())
    {
    }

    void MakeClass()
    {
        factory->DoSomething();
    }
};

例 4

make_unique を使用することで、配列への unique_ptr を作成できます。ただし、make_unique で配列要素を初期化することはできません。

// Create a unique_ptr to an array of 5 integers.
auto p = make_unique<int[]>(5);

// Initialize the array.
for (int i = 0; i < 5; ++i)
{
    p[i] = i;
    wcout << p[i] << endl;
}

その他の例については、「make_unique」を参照してください。

関連項目

スマート ポインター (Modern C++)
make_unique