問題タブ [raii]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - C で書かれたライブラリを使用したスマート ポインター
この質問には関係ありませんが、画像処理ライブラリである OpenCV ライブラリで C++ を使用しています。現在、私はデザインの決定を下しています。
C ライブラリである OpenCV には、そのデータ構造 (CvMat など) が構造体として宣言されています。作成するには cvCreateMat などの関数を使用し、解放するには cvReleaseMat などの関数を使用します。C++ プログラマーとして、cv_scoped
スコープ外になったときに cvReleaseMat を自動的に呼び出す特別なクラスを作成しました ( のようにboost::scoped_ptr
)。
私が今気付いているのは、ケースでも使用できればいいのにということauto_ptr
ですshared_ptr
。時間の無駄は言うまでもなく、自分自身cv_auto_ptr
とcv_shared_ptr
クラスのコードを書くのは悪い考えだと思います。それで解決策を探していて、3つの可能性を思いつきました。
まず、作成済みの cv_scoped クラスを使用できます。名前を に変更してからcv_ptr
、次のようなスマート ポインターを使用しますstd::auto_ptr<cv_ptr>
。ただし、これに関する厄介なことは、常に 2 回逆参照する必要があることです。
暗黙的な変換を宣言できるように見えることはわかっていますが、実際にはできませんでした.OpenCVの関数のほとんどにはパラメータ void* があるため、暗黙的な変換は呼び出されません. 二重逆参照を行う必要のない方法でこれを行う方法が本当に欲しいです。
第二に、どうにかしてオーバーライドすることができoperator delete
ました。これを CvMat (および他のいくつかの) 型に適用したいだけなので、グローバル演算子 delete をオーバーライドしたくありません。ただし、ライブラリを変更できないoperator delete
ため、CvMat 構造体に追加できません。したがって、これがどのように機能するかはわかりません。
第三に、自分のauto_ptr
, scoped_ptr
, and を書き直すことができましたshared_ptr
。大規模なクラスではないので、それほど難しくはありませんが、これは設計が悪いと感じています。私がこれを行うとしたら、おそらく次のようなことをするでしょう。
私の状況であなたはどうしますか?これを理解するのを手伝ってください。
c++ - C ++でスマートポインタを実装するための最良の方法は何ですか?
私はさまざまなスマートポインターの実装を評価してきましたが(うわー、そこにはたくさんあります)、それらのほとんどは2つの大まかな分類に分類できるようです。
1)このカテゴリは、参照されるオブジェクトの継承を使用して、参照カウントがあり、通常はup()およびdown()(またはそれらに相当するもの)が実装されているようにします。IE、スマートポインターを使用するには、ポイントしているオブジェクトは、ref実装が提供するクラスから継承する必要があります。
2)このカテゴリは、参照カウントを保持するためにセカンダリオブジェクトを使用します。たとえば、スマートポインターをオブジェクトに直接向ける代わりに、実際にはこのメタデータオブジェクトを指します...参照カウントとup()およびdown()の実装を持っている人(そして通常、ポインターのメカニズムを提供する人)スマートポインタが演算子->()を適切に実装できるように、ポイントされている実際のオブジェクトを取得します。
これで、1には、カウントを参照するすべてのオブジェクトが共通の祖先から継承するように強制されるという欠点があります。これは、ソースコードを制御できないカウントオブジェクトを参照するためにこれを使用できないことを意味します。に。
2には、カウントが別のオブジェクトに格納されているため、既存の参照カウントオブジェクトへのポインタが参照に変換されているという状況が発生した場合、おそらくバグが発生するという問題があります(つまり、カウントが実際のオブジェクトでは、新しい参照がカウントを取得する方法はありません... ref to refコピーの構築または割り当ては、カウントオブジェクトを共有できるため問題ありませんが、ポインタから変換する必要がある場合は、完全にホースで固定されています)..。
さて、私が理解しているように、boost :: shared_pointerはメカニズム2、またはそのようなものを使用しています...とはいえ、私は自分の決心を完全に決めることはできません。私はこれまで本番コードでメカニズム1のみを使用しました...誰かが両方のスタイルの経験がありますか?または、おそらくこれらの両方よりも優れた別の方法がありますか?
c++ - C++ 例外を使用するのが適切なのはいつですか?
メモリを動的に割り当てる必要があるクラスを設計しようとしています..
構築中に必要なメモリを割り当てる予定でしたが、失敗したメモリ割り当てをどのように処理すればよいですか? 例外をスローする必要がありますか? 例外は「例外的な」ケースにのみ使用する必要があることをどこかで読みましたが、メモリ不足は私にとって例外的なケースではないようです..
代わりに別の初期化ルーチンでメモリを割り当て、エラーをチェックしてから、クラス インスタンスを正常に破棄する必要がありますか?
または、代わりに例外を使用する必要がありますか? これらのメモリ割り当てが失敗した場合、クラスは何の役にも立ちません..
編集:コンセンサスは、メモリ不足は例外的なケースであるということです。
これについてどうやって行くか見ていきます..ありがとう.. :)
garbage-collection - ガベージコレクションの副作用?
これは非常にクローズできる質問かもしれませんが、私は壁にくっついているのを見るタイプです. ガベージ コレクトされたランタイムによって提供されるメモリおよび有効期間管理のすべての利点について、アプリケーションとそのガベージ コレクタの間の競合状態によって引き起こされるプログラムの不確定性の注目すべきケースはありますか? この種のことに対する防御的なプログラミングのゲシュタルトが出現しましたか? 確かに、RAII に慣れているプログラマーは、GC の存在下で教訓を学ばなければなりません。
c++ - 用語と概念の意味を理解する-RAII(リソース獲得は初期化です)
C ++開発者は、RAIIとは何か、なぜそれが重要なのか、そして他の言語との関連性があるかどうかについて、よく説明していただけますか?
私は少し知っています。「ResourceAcquisitionisInitialization」の略だと思います。ただし、その名前は、RAIIが何であるかについての私の(おそらく間違った)理解とは相容れません。RAIIは、スタック上のオブジェクトを初期化する方法であり、それらの変数がスコープ外になると、デストラクタが自動的に実行されるという印象を受けます。リソースをクリーンアップするために呼び出されます。
では、なぜ「スタックを使用してクリーンアップをトリガーする」(UTSTTC:)と呼ばれないのでしょうか。そこからどうやって「RAII」にたどり着きますか?
そして、ヒープ上に存在する何かのクリーンアップを引き起こす何かをスタック上にどのように作成できますか?また、RAIIが使えない場合もありますか?ガベージコレクションを希望したことはありますか?少なくとも、他のオブジェクトを管理させながら、いくつかのオブジェクトに使用できるガベージコレクターはありますか?
ありがとう。
c++ - ifstream を手動で閉じる必要はありますか?
close()
を使用する場合、手動で呼び出す必要がありstd::ifstream
ますか?
たとえば、コードでは次のようになります。
file.close()
手動で呼び出す必要がありますか? ファイルを閉じるためにRAIIifstream
を利用すべきではありませんか?
c++ - RAII と初期化されていない値
簡単な質問:
単純なベクトル クラスがある場合:
RAII の概念はここにも当てはまりますか? つまり、すべての値をいくつかの値に初期化するコンストラクターを提供します (初期化されていない値が使用されるのを防ぐため)。
EDITまたは、オブジェクトを難読化する前にメンバー変数を初期化するようユーザーに明示的に要求するコンストラクターを提供します。
すなわち
プログラマーが値を使用する前に値を初期化するのを忘れるのを助けるために RAII を使用すべきですか、それとも開発者の責任ですか?
それとも、RAII の見方が間違っているのでしょうか。
私は意図的にこの例を途方もなく単純にしました。私の本当の質問は、たとえば次のような複合クラスに答えることでした。
ご覧のとおり...すべてのメンバーを初期化するためにコンストラクターを作成する必要がある場合、それは非常に面倒です。
考え?
c++ - C++ RAII が動作しない?
C++ で RAII を使い始めたばかりで、小さなテスト ケースをセットアップしています。コードがひどく混乱しているか、RAII が機能していません! (前者だと思います。)
私が実行した場合:
コメントアウトされた例外を除いて、次のようになります。
予想通りですが、例外があります:
そのため、スコープ外に出てもオブジェクトは破壊されません。これは RAII のすべての基礎ではありませんか。
ポインタと修正は大歓迎です!
c++ - C++ でブラケット クラスを使用しない理由は何でしょうか?
多くの場合、次のタスクを達成するために必要です: 何かの状態を変更し、アクションを実行してから、状態を元に戻します。たとえば、Win32 GDI では、背景色を変更し、描画を行ってから色を元に戻す必要があります。
直接行うことができます:
または、コンストラクターで前方変更を行い、デストラクタで後方変更を行うブラケット クラスを介して:
ブラケット クラスの利点は明らかです。変更の間に例外がスローされた場合、変更は正しく元に戻されます。短所は何ですか?