12

重複の可能性:
スマート ポインターとは何ですか? また、いつ使用する必要がありますか?

私は記事を読んでいて、の使用を示す小さな例を見つけましたboost::scoped_ptr<T>:

#include <cstdlib>
#include <iostream>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>

static int count = 0;

class printer
{
    int m_id;

public:
    printer(void) :
        m_id(count++)
    {
    }

    ~printer(void)
    {
        std::cout << "Printer " << m_id
                  << " destroyed" << std::endl;
    }
};

int
main(void)
{
    boost::scoped_ptr<printer> p1(new printer);
    boost::scoped_ptr<printer> p2(new printer);
    std::cout << "Exiting test program" << std::endl;

    return EXIT_SUCCESS;
}

この記事で唯一理解できなかったのは、次のステートメントです。

を使用してscoped_ptr、所有権の譲渡が意図されていない、または許可されていないことを示します。

このトピックの初心者として始めるのは間違った記事だったのかもしれませんが、上記の行は正確には何を意味するのでしょうか?

4

1 に答える 1

19

ほとんどのスマート ポインターは、指しているオブジェクトの所有権を持っています。必要なときにそのオブジェクトを破棄する責任があります。ただし、スマート ポインターが異なれば、所有権のセマンティクスも異なります。つまり、所有権がどのように転送されるか、または転送されないか、オブジェクト間でどのように共有されるか、いつオブジェクトを削除する必要があるかなどを、そのスマート ポインターのユーザーに伝えます。特定のスマート ポインターを使用すると、そのオブジェクトの所有権に関する意図が説明されます。所有権は、他の関数またはオブジェクトに転送できます。

boost::scoped_ptr非常に厳密な所有権のセマンティクスがあります。所有権の譲渡を一切許可しません。コピー不可にすることでこれを実現します (そのため、別の関数に値で渡すことはできません)。

別の例として、 astd::unique_ptrもかなり厳密です。その特別な能力は、移動できることです。を右辺値として関数に渡すstd::unique_ptrと、その関数はオブジェクトの所有権を盗むことができます。オリジナルstd::unique_ptrはその所有権をすぐに失います。これにより、所有権が 1 つのみに保持されることが保証されstd::unique_ptrます。

boost::scoped_ptrC++11の に相当するのは aconst std::unique_ptrです。これは、それを作成するとconst移動が妨げられ、所有権を譲渡できないためです。

所有権のセマンティクスがいかに重要であるかを簡単に確認するには、例を示します。悪意のある開発者のライブラリを使用していて、実装がわからない関数があるとしましょう。たとえば、次のようになります。

cat* foo();

この関数が へのポインタを返すことはご存知でしょうcat。ただし、これは生のポインターです。deleteある時点で( を使用して) cat を破棄する必要があるのか​​、それともライブラリーが代わりに処理してくれるのかはわかりません。オブジェクトが実際に動的に割り当てられたかどうかさえわかりません。ライブラリがまだ を保持しているかどうかはわかりませんcat。以前は、このような関数がある場合、何をすべきかを見つけるためにドキュメントを調べる必要がありました。ただし、生のポインターに加えてスマート ポインターがあるため、生のポインターには独自の所有権セマンティクスがあり、すべての中で最も緩和されています。cat「あなたがそれを渡す限り、私がこれを有効に保つことを信じてください。ただし、私が管理します。あまり長く保管しないでください。」

ただし、賢明で親切なライブラリ開発者は、この関数を次のように記述します。

std::unique_ptr<cat> foo();

それで、これはどのように役立ちますか?まあ、多くのstd::unique_ptrことを教えてくれます。cat関数がオブジェクトの所有権を放棄していることを示しています。これcatはあなたの唯一の責任です。また、それについて考える必要がないため、スマートなポインターを提供するのにも非常に役立ちますdelete。ポインターを使用するだけで、スコープ外になると、オブジェクトは破棄されます。または、必要に応じて、所有権を別の関数に譲渡できます。

ただし、これは、1 つのポインターだけが所有権を持つという意味ではありませんcat。誇り高い新しい所有者として、次に何が起こるかを決めるのはあなた次第です. の所有権の共有を開始することを決定することは、完全に合理的ですcat

std::unique_ptr<cat> up = foo();
std::shared_ptr<cat> sp(up.release());

賢明で親切なfooライブラリ開発者は、自分の意図が何であるかをあなたに話しただけです。彼女はあなたに を与えcat、今ではあなたが所有者です。独自の所有権セマンティクスを提供できるようになりました。

このように、aboost::scoped_ptrは貪欲なcat買いだめのようなもので、誰とも共有せcatず、猫を誰にも渡さず、死ぬまで飼っています。

于 2013-02-02T01:07:39.807 に答える