13

次のコードがあるとします。

class B { /* */ };

class A {
    vector<B*> vb;
public:
    void add(B* b) { vb.push_back(b); }
};


int main() {

    A a;
    B* b(new B());
    a.add(b);
}

この場合、すべての生ポインタB*を を通じて処理できるとしますunique_ptr<B>

驚いたことに、 を使用してこのコードを変換する方法を見つけることができませんでしたunique_ptr。数回試行した後、コンパイルできる次のコードを思いつきました。

class A {
    vector<unique_ptr<B>> vb;
public:
    void add(unique_ptr<B> b) { vb.push_back(move(b)); }
};


int main() {

    A a;
    unique_ptr<B> b(new B());
    a.add(move(b));
}

だから私の簡単な質問:これはそれを行う方法ですか、特に、それmove(b)を行う唯一の方法ですか?(右辺値参照について考えていましたが、完全には理解していません。)

unique_ptrそして、私が見つけることができなかった移動セマンティクスなどの完全な説明へのリンクがある場合は、遠慮なく共有してください。

編集http://thbecker.net/articles/rvalue_references/section_01.htmlによると、私のコードは問題ないようです。

実際、 std::move は単なるシンタックス シュガーです。クラス X のオブジェクト x を使用move(x)すると、次のようになります。

static_cast <X&&>(x)

右辺値参照にキャストするため、これら 2 つの移動関数が必要です。

  1. 関数「add」が値渡しするのを防ぎます
  2. push_backB のデフォルトの移動コンストラクタを使用します

どうやら、 「追加」関数を参照渡し(通常の左辺値参照)に変更std::moveした場合、2番目は必要ありません。main()

このすべての確認をお願いしたいのですが...

4

4 に答える 4

9

はい、これはそれが行われるべき方法です。mainからに所有権を明示的に譲渡していAます。これは基本的に以前のコードと同じですが、より明示的で信頼性が大幅に向上しています。

于 2012-09-23T12:23:24.733 に答える
0

C ++ 14以降、コードはmain少し簡略化できます。

a.add( make_unique<B>() );

B内括弧内に のコンストラクターの引数を入れることができます。


生のポインターの所有権を取得するクラス メンバー関数を検討することもできます。

void take(B *ptr) { vb.emplace_back(ptr); }

対応するコードは次のようにmainなります。

a.take( new B() );

もう 1 つのオプションは、ベクター メンバーを追加するために完全転送を使用することです。

template<typename... Args>
void emplace(Args&&... args)
{ 
    vb.emplace_back( std::make_unique<B>(std::forward<Args>(args)...) );
}

そしてメインのコード:

a.emplace();

B前と同じように、括弧内にコンストラクター引数を入れることができます。

実例へのリンク

于 2016-01-19T05:23:35.330 に答える
0

だから私の簡単な質問:これはそれを行う方法ですか、特に、これは「move(b)」がそれを行う唯一の方法ですか? (右辺値参照を考えていましたが、完全には理解していません...)

そして、私が見つけることができなかった移動セマンティクスunique_ptr ...の完全な説明へのリンクがある場合は、躊躇しないでください.

恥知らずなプラグイン、「メンバーへの移動」という見出しを検索します。それはあなたのシナリオを正確に説明しています。

于 2014-06-22T14:22:21.140 に答える