1

これらのクラスをコンパイルするための clang (Apple LLVM バージョン 4.2 (clang-425.0.28)) を取得できません。

struct A {
    int f(){return 2;}
};
class Cl{
     std::unique_ptr<A> ptr;

public:
     Cl(){ptr = std::unique_ptr<A>(new A);}

     Cl(const Cl& x) : ptr(new A(*x.ptr)) { }
     Cl(Cl&& x) : ptr(std::move(x.ptr)) { }
     Cl(std::unique_ptr<A> p) : ptr(std::move(p))  { }

    void m_ptr(std::unique_ptr<A> p){
        ptr = std::unique_ptr<A>(std::move(p));
    }
    double run(){return ptr->f();}
};

次のようにコンストラクターを実行したいと思います。

std::unique_ptr<A> ptrB (new A);
Cl C = Cl(ptrB);

しかし、これを行うと、次のコンパイラ エラーが発生します: ../src/C++11-2.cpp:66:10: エラー: 'std::unique_ptr' C.m_ptr( ptrB);

実行することでコンパイラの問題を解決できますCl(std::move(ptrB))が、これは実際には A の所有権を ptrB から移動しません: ランタイムptrB->f()クラッシュを引き起こすことなく実行できます...std::moveクラス インターフェイスでの実装を非表示にします。

前もって感謝します。

4

1 に答える 1

2

ptrB はCl のコピー コンストラクターに値によって渡されるため、Cl(ptrB) への呼び出しは、unique_ptr の (明らかに無効になっている) コピー コンストラクターを呼び出す ptrB のコピーを作成しようとします。ptrB の余分なコピーを作成しないようにするには、次の手順を実行します。

Cl C = Cl(std::unique_ptr<A>(new A)); //A temporary is created on initialization, no extra copy steps performed

または:

std::unique_ptr<A> ptrB (new A);
Cl C = Cl(std::move(ptrB)); //Move semantics used. Again, no extra copy steps

または、コピー コンストラクターで参照渡し (右辺値または左辺値) を使用します。

class Cl{

//...
public:
//...
     Cl(std::unique_ptr<A> &p) : ptr(std::move(p))  { }

//...

};

std::unique_ptr<A> ptrB (new A);
Cl C = Cl(ptrB);

PSああ、ちなみに、std::move()の後、オブジェクトは未指定ですが有効な状態のままです。これは、引き続き ptrB->f() を呼び出すことができ、2 を返すことが保証されていることを意味すると思います:)

于 2013-07-18T18:24:41.797 に答える