2016-09-21 8 views
2

のはAをいくつか自明移動し、構成可能を見て、(ない自明)、コピー構築可能(それでもコピー構成可能)ユーザ定義(クラス)を入力してみましょう:次にA(移動-建設かの移動簡単なコピーと移動の操作は異なりますか?

struct A 
{ 
    A() = default; 
    A(A const &) {} 
    A(A &&) = default; 
}; 

move-assignment)は、以下のように文字通りに完結します。ソースのビット単位でがコピーされ、操作名が「動いている」にもかかわらず、宛先にがコピーされました。些細な動きの中で右手側は(正式に)constではないが、操作全体のトリビアルは右手側の(実際の)非可変性を必要とするのではないか?私の考えでは、些細なコピー操作と簡単な移動操作は、(メモリ、メモリレイアウト、ビットなどの点で)その本質的に全く同じであることを意味します。私は正しい?

もしそうなら、私は、単純に移動可能ではあるが、ユーザーコードには単純にコピーコンストラクタブルなタイプではないと思うなら、明らかに反パターンを見ます。私は正しい?

このような人工的であるが使用可能なタイプの例がありますが、それは単純にコピーコンストラクタブル/アサイナブルではありませんが、

+3

"私の考えでは、些細なコピー操作と簡単な移動操作は、深い性質(メモリ、メモリレイアウト、ビットなど)でまったく同じであることを意味します。 。 – ildjarn

+0

ええ、その質問は全くこの問題に関連していません。 – Barry

+2

"エッジ"の場合:コピーコンストラクタブルではないタイプは、自立的にコンストラクタブルであり、簡単にコピーコンストラクタブルではありません(削除されたコピーコンストラクタは自明ではありません)。 – Holt

答えて

2

型に、単純な移動コンストラクタを持たない単純なコピーコンストラクタを使用できるユースケースはありますか?確かに。

たとえば、移動したときに常に空になるポインタラッパー型を持つと便利です。コピーコンストラクタが自明ではない理由はありませんが、移動コンストラクタは古い値をNULLに設定する必要があります。

template<typename T> 
class empty_on_move 
{ 
    T *ptr_; 

public: 
    empty_on_move(const empty_on_move&) = default; 
    empty_on_move(empty_on_move &&other) : ptr_(other.ptr_) {other.ptr_ = nullptr;} 
... 
}; 

empty_on_move、それはそれの複数のコピーを持ってOKだ理由である、オブジェクトを所有していません。それは、ポインタから移動するときに、ポインタがよく理解された状態にあることを確認するためだけに存在します。そのため、is_trivially_copy_constructible<empty_on_move<T>>が真であり、is_trivially_move_constructible<empty_on_move<T>>は偽です。

これは主に、特定の動作のポインタを与える他のクラスの内部で使用するためのものです。そうすれば、移動コンストラクタ/代入に明示的にコードを書いて、それらのフィールドをNULLにする必要はありません。


あなたは本当に間違った質問をしています。どうして?答えは重要ではないからです。

コピー/移動コンストラクタ/割り当ての重要性は、タイプがTrivially Copyableである必要があるときだけです。 は、memcpyなどの使用を許可するプロパティーであり、個々の操作の些細なものではありません。ほとんどコピー可能なプロパティでは、コピー/移動コンストラクタ/代入とデストラクタすべては簡単です(またはC++ 14では削除されています)。

いくつかのタイプのラッパーを作成している(または合計/製品タイプを記述している)場合、そのタイプのプロパティを公開したい場合は、Trivial Copyabilityを公開するだけで十分です。つまり、T(またはTs...)を簡単にコピーできる場合は、あなたのタイプも自明にコピー可能でなければなりません。

しかし、それ以外の場合は、ちょうどTがするので、簡単なコピーコンストラクタを持つ必要はありません。

+0

trivial destructorを持つ必要がありますtriviallyコピー可能な型はなぜですか?論理的には、それは全く必要ではありません。 – Orient

+1

@Orient:これらすべての操作が簡単な型は、C++のオブジェクトモデルに関する限り、そのビットの値を超えた状態を持たない型です。したがって、任意のストレージスペースへのビット単位のコピーは妥当なアクションです。デストラクタが自明でない場合、デストラクタはオブジェクトを単なるビットブロック以上にする何かをしているかもしれません。したがって、ビット単位のコピーはもはや合理的な動作ではありません。 'lock_guard'を考えてみましょう。コピー/移動コンストラクタ/割り当てを削除しました。しかし、それは非自明なデストラクタを持っています。ビット単位でコピーすることが許されるべきですか? *もちろん違います*。 –

+0

'lock_guard'のコピー禁止は、削除されたコピー/移動コンストラクタ/代入演算子ではっきりと表現されます。デストラクタのトリビアルは関連するものではありません。 '!std :: is_copy_constructible'をimpy'!std :: is_trivially_copy_constructible'に設定します。 – Orient

関連する問題