2015-11-02 18 views
5

は、私が持っていると仮定します。auto a = A(3)とA a(3)の違いは何ですか?

struct A 
{ 
    A(int x) : m_x(x) { } 
    A(A&&) = delete; 
    int m_x; 
} 

とを:

A a(3); // Ok 
auto a = A(3); // Error: function A(int&&) cannot be referenced - it's a deleted function 

はなぜ動くのコンストラクタに、後者の呼び出し?なぜ、これらの2つのステートメントは、生成されたコードの点で異なりますか?

答えて

4

なぜ両方のコードパスが同じであると思われますか?

あなたは明らかaauto a)を割り当て、第二の例では無名のオブジェクトを作成してから(私たちは、一時的なオブジェクトの話をしているので、移動している)aに一時的にコピーします。

+0

あなたの最初のコメントについて、私の印象は、これはしばしば "これは、通常は出てこない技術を除いて同じ"として紹介されているということです。しかし、多分私はOPの口に単語を入れています。 – Hurkyl

+1

そのような人物を紹介する人は、無能に解雇されるべきです。 – Blindy

+0

インテントが明確に同じ場合、コンパイラが異なるコードを生成するのはなぜですか?プログラマがその動作を望むケースはありますか? – Shmoopy

-1

コンパイル時に必要な関数/コンストラクタを定義する必要があるため、どちらのコンパイラでも同じコードが生成されることはありません。 このように考えると、最適化はコンパイル/コード解析後に行われますが、この場合エンドコードは同じであるはずです。

+0

コードは同じ機械コード*でコンパイルされます*最適化は* – CoffeeandCode

6

auto a = A(3);は、右辺のタイプがAなので、A a = A(3);と同じ意味です。

これは、それがどのように見える正確に何を意味:A(3)3で初期化された一時的なAを作成し、A a = _____意味:初期化子として_____aと呼ばれるAを作成します。

一時的に作成し、aに初期化子として渡してから一時的に破棄します。このタイプの初期化(=)は、コピー初期化と呼ばれます(ただし、「コピー」と混同しないでください)。

コンストラクタは、Aを受け入れるaを構築するように選択されます。これは、コピーコンストラクタまたは移動コンストラクタのいずれかでなければなりません。 Aには、移動コンストラクタとコピーコンストラクタがあります。後者は、ユーザーが宣言した移動コンストラクターが存在するため、暗黙的に生成され、削除済みとして定義されます。

削除されたとして定義されても、過負荷の解決には影響しません。この場合、コピーコンストラクタよりも移動コンストラクタが優先されます。

コードでdeleted関数が呼び出されようとしています。そのため、エラーが発生します。

移動コンストラクタが削除されなかった場合は、コピーエリートが適用されます。変数が一時的なものから初期化される場合や、ローカル変数が値によって返される場合があります。規則は、コンパイラがaと一時オブジェクトの両方に同じメモリを使用し、コピー/移動コンストラクタの呼び出しを省略することができます。

ほとんどの/すべてのコンパイラは、実際にこの状況でこれを実行します。したがって実際にはauto a = A(3);と書くことができ、実際には不必要な動きはありません。あなたが何かを出力するあなたの移動コンストラクタ用のコードを書くなら、何も出力されていないことが分かります。

不必要なコピーがないことを絶対に確かめたい、または使用可能なコピーも移動コンストラクタもないオブジェクトを作成する場合は、不要なコピーを指定するコードの作成をやめてください! A a(3);で十分です。

+0

ですこの場合、コンストラクタが削除されたこの場合、コンパイラが移動を削除できるかどうかは疑問ですか? – Mikhail

+0

@Mikhail申し訳ありませんが、質問を誤解しました。私の答えを更新する –

関連する問題