2

移動のセマンティクスについて何か理解していないのではないかと思います。次のコードが与えられた場合、デバッガー(MSVC2010SP1)が次の順序でプロキシのメンバーを呼び出すことを期待します。

  • Proxy(Resource*)で一時的なものを構築するgetProxy
  • Proxy(Proxy&& other)移動構築p
  • ~Proxy()移動によって内臓を奪われた一時的なものの空のシェルを破壊する
  • ~Proxy() p範囲外になります

    class Resource
    {
        void open(){}
    public:
        void close(){}
        Proxy && getProxy();
    };
    class Proxy
    {
        Resource *pResource_;
        Proxy(const Proxy& other); //disabled
        Proxy& operator=(const Proxy& other); //disabled
    public:
        Proxy(Resource *pResource):pResource_(pResource){}
        Proxy(Proxy&& other):pResource_(other.pResource_){other.pResource_ = nullptr;}
        ~Proxy()
        {
            if(pResource_)
                pResource_->close();
            pResource_ = nullptr;
        }
    };
    
    Proxy && Resource::getProxy()
    {
            open();
            return Proxy(this);
    }
    
    //somewhere else, lets say in main()
    Resource r;
    {
        auto p = r.getProxy(); 
    }   // p goes out of scope
    

代わりに、順序は次のとおりです。

  • Proxy(Proxy*)
  • ~Proxy() //これはすでにclose()予想よりも早く呼び出します
  • Proxy(Proxy&& other) //破壊後に移動するp.pResource_と、nullptr
  • ~Proxy() //pスコープ外になります

これは私には意味がありません。私がやろうとしているのは、あるオブジェクトから別のオブジェクトへの移動コンストラクターを介してリソースを閉じるジョブを渡すプロキシクラスの存続期間を追跡することです。

4

2 に答える 2

6

getProxy()一時オブジェクトへの参照を返します。これは関数の最後で範囲外になり、ダングリング参照になります。

于 2013-02-04T14:23:52.783 に答える
2

右辺値参照によって返されても、実際には何も移動されません。参照によって返されるだけです。ただし、右辺値参照を返す関数を呼び出す式は (左辺値ではなく) xvalue であるため、左辺値参照を返す場合とは異なります。その後、xvalue (右辺値式のサブセットとして) を移動できます。左辺値参照を返す関数の返されたオブジェクトから移動したい場合はstd::move、右辺値にするために を使用する必要があります。

実際に右辺値参照を返したいと思うことはほとんどありません。漠然と一般的な唯一の用途は、オブジェクトのプライベート メンバーの移動を許可することです。関数からオブジェクトを返すときにオブジェクトを移動したい場合は、値で返すだけです。あなたの場合、戻り値の型getProxyが just だったProxy場合、一時オブジェクトは返されたオブジェクトに移動され、次にそれが移動されますp(省略されている場合は保存してください)。

あなたが持っているように、一時オブジェクト(によって構築されたProxy(this))はステートメントの最後で破棄されますreturn- これはデストラクタの最初の呼び出しです。返された参照は現在、無効なオブジェクトを参照しておりp、この無効な参照から移動することによって構築されています。これにより、未定義の動作が発生します。

于 2013-02-04T14:34:50.037 に答える