2016-08-30 5 views
2

私は構造体にコピー不可能な(コピー可能ではあるが非常に高価な)メンバを持っていて、呼び出した場合に必要なメンバ関数があり、メンバの所有権を移譲する。次のデモコードを参照してください:メンバ関数の最後でデストラクタへの呼び出しをバイパスする方法はありますか?

class A{ 
    // ... 
}; 
struct s{ 
    A instance; 
    A? take(){ // originally named get(), as mentioned in comment, for clarity 
     return instance?; 
    } 
}; // Even after s is destroyed, instance should keep on 

言い換えると、私はその後、instanceの寿命を延ばす他のコンテキストでそれを使用したいです。私はreturn std::move(instance)を含むいくつかの方法を試してみましたか、またはオブジェクトを一時変数に明示的に解放しましたが、どれも働いていませんでした。彼らは常にインスタンスのデストラクタを呼び出します。

どのように私はそれを達成することができます、const参照ヘルプを返しますか?

+1

「静的」にしますか?または、名前空間レベルで宣言します。 – Nawaz

+0

'インスタンス 'は' s'のすべてのインスタンスに一意ですが、ちょっと厄介です。だから静的ではありません。 – YiFei

+0

's'のインスタンスではない場合、誰が*このインスタンスを*所有する予定ですか?誰かがこれを*所有していなければなりません。あるいは、スコープ*にする必要があります。 – Nawaz

答えて

5
  • それは、静的またはスレッド記憶域期間を持っていない限り、オブジェクトの寿命は、そのレキシカルスコープを超えて拡張することができません。
  • can notstd::exitを呼び出すか、またはプログラムをクラッシュする以外に、スコープ外になるオブジェクトの暗黙的なデストラクタ呼び出しを抑制します。

これはXY problemのように見えます。ほとんどの場合、実際の解決策は、s::instanceから戻り値にリソースを移動するためにがA(値で)に戻り、std::moveを使用することになり、デストラクタs::instanceはno-opになります。

A take() { 
    return std::move(instance); 
} 

実際の問題を教えていただけないかどうかはわかりませんが、

+0

このようにして、外部関数と構造体は所有権を共有し、構造体が消滅すると非常に危険です。 – YiFei

+0

@ YiFei移動コンストラクタを正しく書くと、リソースのすべての所有権が 'instance'から返されたオブジェクトに転送されます。 – Brian

0

インスタンスの移動コンストラクタを正しく設定する必要があります。そのため、リソースを取り、ソースを空のシェルとして残します。そうすれば、std :: move()はメンバーをシェルに変換し、あなたが望むことができる完全なオブジェクトを与えます。デストラクタは依然として呼び出されますが、本質的にノーオペレーションになります。これを達成するための

0

一つの方法、すなわち完全デストラクタの呼び出しを避けるため、スマートポインタである:

struct s 
{ 
    std::unique_ptr<A> instance; 
    std::unique_ptr<A> get() { return std::move(instance); } 
}; 

デフォルト・構築sAを含むようにしたい場合は、次にようsにコンストラクタを与えます:

s(): instance(new A) {} 

完全転送を使用して、必要に応じてコンストラクタ引数をAのコンストラクタに渡すことができます。


(IはプリC++コードベース11に使用した)別の可能な解決策は、Aactive名前変更可能なブール・フラグを与えることです。操作中にコピーコンストラクタとコピー代入演算子にこのフラグを「移動」させます。次に、デストラクタは、フラグが設定されているインスタンスのリソースのみを破棄します。しかし、C++ 11では、移動セマンティクスが利用可能であるため、これはもはや必要ではありません。

関連する問題