スマート ポインター + 「これ」は有害と見なされるなどの関連する質問がありますか? しかし、彼らは私のケースを処理しません。これらの質問はすべて、スマート ポインターをカウントする参照の場合に生の this ポインターを公開することに関するものです。ただし、私の問題は、公開するthis
のではなく、メソッドでのみ使用することですが、おそらく長期間使用することです。
次のコードを検討してください。
class X{
void foo(){...} //Performs some long running task
}
shared_ptr<X> x;
void bar(){
x->foo();
}
さて、いくつかのコードはfoo
オブジェクト x のメソッドを呼び出します。x の背後にあるインスタンスへの唯一のスマート参照は、1 つの shared_ptr x であると考えてください。ここで、foo は、他の関数などを呼び出す長時間実行されるタスクを実行します。
ここで、foo の実行中に、別のスレッド、シグナル ハンドラー、または での再帰呼び出しによってfoo
、参照が変更またはクリアされるとしますx
。これにより、オブジェクトの削除がトリガーされます。これでthis
、コール スタック上のポインターはfoo
、削除されたオブジェクトを指します。したがって、さらにコードを実行するfoo
と、予測できない結果が生じます。
これを回避する方法は?つまり、参照カウントによって処理されるオブジェクトのメソッドの実行中は常に、一部のコードがオブジェクトへの参照をクリアし、メソッド呼び出しが失敗したり、奇妙な結果を生成したりする危険性があります。問題はセマンティクスです。参照カウントは、オブジェクトへの参照がこれ以上ないと判断して削除しますが、これは正しくありませんthis
。参照はまだありますが、悲しいことに、それはスマート ポインターではありません。
のようなものがあることは知っていenable_shared_from_this
ますが、参照カウントされる可能性のあるオブジェクトのすべてのメソッドを常に書き直して、最初に共有ポインターを取得しthis
、次にそのポインターを使用して、この問題を回避する必要がありますか? これによりすべてのメソッド コードが乱雑になり、さらに失敗する可能性もありx
ます。その後、物事は再び失敗します。
したがって、一般的な質問は次のとおりです。どのような種類のスマート ポインターを使用する場合でも、管理対象オブジェクトへのメソッド呼び出し中に安全を確保するにはどうすればよいでしょうか? this
メソッド内のポインターが無効にならないようにするにはどうすればよいですか? 最初のステートメントで使用するすべてのメソッドを書き直すことenable_shared_from_this
は良い解決策ですか?
それとも、参照がまだコール スタック上にあるときに参照をクリアするコードは、単純に形式が正しくないのでしょうか? しかし、そうであれば、複数のスレッドと複雑な再帰呼び出しが使用されると、形式が正しくないコードを記述するのは困難です...