問題タブ [copy-assignment]
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++(C#から来た)が初めてで、最初からそのメモリを取得したいと思っています。
次の抜粋では、型の変数がWorldChunkCoordinates
値によってのインラインコンストラクターに渡されWorldChunk
、渡された座標がに割り当てられWorldChunk::Coordinates
ます。これもコピー操作だと思います。
(コピー代入操作?)
私の仮定が正しければ、インスタンスを 2 回コピーするので、これはばかげています。値で渡し、参照ポインターで割り当てると、はるかにパフォーマンスが向上すると思います。しかしWorldChunk::Coordinates
、ポインタでも参照でもありません。
プログラムがインスタンスを 2 回コピーしないようにする方法はありますか?
もしそうなら、どのように?
また、= による割り当ては常にデフォルトでコピー操作ですか?
そして:特定のクラスに、参照によってコピーする別のコピー割り当て操作がある可能性があることをどのように知る必要がありますか?
c++ - 生成されたコピーおよび移動演算子?
現在、私はScott Meyersの『 Effective Modern C++』という本を読んでいます。
私の誤解は、次の部分(根拠)から来ています。
2 つのコピー操作は独立しています。一方を宣言しても、コンパイラが他方を生成するのを妨げることはありません。したがって、コピー コンストラクターを宣言し、コピー代入演算子を宣言しない場合に、コピー代入を必要とするコードを記述すると、コンパイラによってコピー代入演算子が生成されます。同様に、コピー代入演算子を宣言し、コピー コンストラクターを宣言しない場合でも、コードにコピー構築が必要な場合、コンパイラーはコピー コンストラクターを生成します。これは C++98 でも当てはまり、C++11 でも当てはまります。
2 つの移動操作は独立していません。どちらかを宣言すると、コンパイラはもう一方を生成できなくなります。論理的根拠は、たとえば、クラスの移動コンストラクターを宣言する場合、コンパイラーが生成するデフォルトのメンバーごとの移動とは異なる移動構築の実装方法について何かがあることを示していることです。また、メンバーごとの移動の構築に問題がある場合は、メンバーごとの移動の割り当てにも問題がある可能性があります。したがって、移動コンストラクターを宣言すると、移動代入演算子が生成されなくなり、移動代入演算子を宣言すると、コンパイラーが移動コンストラクターを生成できなくなります。
論理的根拠の部分は、コピー コンストラクターとコピー代入演算子のペアにも適用できると思いますね。したがって、コピー コンストラクターを宣言する場合は、既定のメンバーごとのコピーが適切でないことを示します。そして、私がこれを言うなら、おそらくコピー代入演算子もユーザー定義する必要があります。
素晴らしい本だと思いますが、この時点では、この理論的根拠は明確ではありません。これを助けて説明してください。ありがとう。
c++ - fill insert() - コンストラクターをコピーし、割り当て noexcept ステータスをコピーしますか?
- STL コンテナー要素には
noexcept
、コピー コンストラクターとコピー代入演算子が必要ですか? できれば参考までにお願いします。 - そうでない場合、複数挿入中 (例: fill insert中) に例外が発生したときの STL コンテナーの状態は何ですか。
変更の傍受/拒否を許可する汎用ラッパーを作成しようとすると、問題が発生します。私が思いついた実装は、すべてのコンテナー タイプに特化していない限り (実際にはオプションではありません)、基になるコンテナーのセマンティクスを変更する可能性があります。
たとえばstd::vector
、フィル インサートがあります。
これは、 CopyInsertableと CopyAssignable の両方value_type
である必要があります。値の型がDefaultConstructibleである必要はないことに注意してください。
編集 3 Stroustrup自身 (956 ページの表) は、複数要素の挿入がvector、deque、list、および map のすべてに対して強力な保証を持つことになっていることを示しています。完全な標準ライブラリ操作がアトミックに成功または失敗することを意味します。
編集 4ただし、保証は、関連する操作 (この場合はコピー コンストラクター) 自体が例外をスローしない場合にのみ適用されます。これはまさに私の問題です。
私が理解している限り、これにより 2 つの基本的な実装方法が残ります。
- 新しい要素と copy-assign のダミーエントリを作成します
val
。これは、コンテナー内の既存の要素をコピーすることによってダミー要素を作成できる場合、またはDefaultConstructiblevalue_type
である場合(必須ではありません) にのみ機能します。 - 要素をコンテナ内のそれぞれの場所に直接コピー構築します。これは多かれ少なかれ標準的な実装のようです。
編集2 :この用語は、言語ランタイム/標準によって未定義と考えるように人々に警告しているように見えるため、この未定義の動作とは呼びません。
どちらの実装も、コピー コンストラクターまたはコピー代入演算子のいずれかが例外を発生させると、コンテナーの内容が不明なままになるようです(つまり、例外の後にコンテナーが保持する要素が明確ではありません) 。
編集 1 : これは、メモリ リークや未定義の値など、C++ ランタイムに不適切な動作があると想定しているわけではないことに注意してください。ただし、コンテナの内容は多かれ少なかれ特定されていないようです。特に、コンテナーの内容は (一貫してはいますが) 完全に変更されている可能性があります。
例として、3 番目の (ハイブリッド) メソッドを考えてみましょう。
n
テンプレート オブジェクトのコピーのリストを作成しますval
。- このリストの要素をコピーしてターゲット コンテナーに割り当てます。
違いは、コピー コンストラクターが例外を発生させたときのコンテナーへの影響です。この場合、コピー コンストラクターがスローした場合、コンテナーの内容は変更されません (ただし、コピー代入演算子がスローした場合は未指定のコンテンツが発生します)。ポインターを使用する場合 (つまり、 を使用しない場合std::vector
) は、コピー代入を省略してポインターのみを再配置し、操作をアトミック wrt にすることができます。例外。
コンテナ要素については、noexcept
オブジェクトは を介して作成されますがallocator_traits<value_type>::construct(ptr, args)
、そうではなく、コンテナ要素にコピーコンストラクタ/コピー代入演算子noexcept
がほとんどあるという要件も見つかりません(たとえば、これが必要です)。noexcept
std::shared_ptr
std::unique_ptr
copy-construct および copy-assign の自動生成操作はnoexcept
、それ自体が例外を発生させる可能性のある操作を呼び出す必要がない限り、必要であることに注意してください。
これは私を混乱させ、何かを見逃したと確信していますが、私が間違っていることを証明するかもしれない標準の部分を理解することはできません.
c++ - copy-assign 演算子を使用するときにリソースを削除する必要があるのはなぜですか?
たとえば、私の本の1つからの次のようなコード:
operator= の内部は次のようになります。
最初にポインターを削除する必要がないため、削除するのは冗長に思えます。例外が発生した場合にオブジェクトを適切な状態のままにする方法で書かれていることは言及しましたが、それを過ぎて漏らしませんでしたが、私の代替手段でさえ処理できない例外が発生する可能性はありません。割り当てる前に最初にオブジェクトを削除する必要があるのはなぜですか?
c++ - 動的メモリ割り当て、ポインター メンバーおよびデストラクタ
コピー コンストラクタ、コピー代入演算子、およびデストラクタがどのように機能するかを理解するために、次のダミー クラスを作成しました。
コードでこのクラス型を使用して、それがどのように機能するかをテストしていますが、組み込みのポインター型のメンバーを持つオブジェクトを破棄する場合の影響について考えていました。
このポインターはコンストラクターで初期化され、フリー ストア上の (常に新しい) 動的に割り当てられたメモリを指します。したがって、デストラクタが呼び出されると、破棄されるオブジェクトのメンバーが逆の順序で破棄されます。この場合、int オブジェクトとポインター オブジェクトのみが破棄され、最終的にメモリ リークが発生します (ヒープ上の文字列は解放されません)。
また、このコピー代入演算子を定義すると、オブジェクトを代入するたびにメモリ リークが発生しますか (ポインターはヒープ上の新しいオブジェクトを指し、前者は失われますよね?)。