1

私は移動セマンティクスのいくつかのテストを行っていました、そして私はこれを試しました:

class A{
public:
    A(){printf("A CTOR\n");}
    A(A&) {printf("A CTOR by copy\n");}
    A(A&&){printf("A CTOR by universal reverence\n");}
};

A&& create(){
    A v;
    return std::move(v);
}

auto x{ create() };//this does not compile

float d[]{1.2,1.3,5,6};//this does compile

次のエラーが発生します。

error C3086: cannot find 'std::initializer_list': you need to #include <initializer_list>

初期化リスト機能がCTP2012novでVC11に追加されたため、わかりません。これは、stdlibの更新を待たなければならないためですか?

Scott meyersのスライドからコピーしたので、コードは正しいと思います:Move Semantics、Rvalue References、PerfectForwarding

ご協力ありがとうございました。ちなみに、CTORにコピーで「const」を追加しなかったため 、偽のコピーが発生しました。 一番

4

2 に答える 2

6

中括弧autoは常にstd::initializer_list<T>タイプになります。つまり、基本的にここで何が起こるかは、おそらくここでの意図ではなく、std::initializer_list<A>ここで作成しようとします。ただし、コードは正常にコンパイルされるはずであり、それはVS最新のCTPコンパイラのバグである可能性があります。xA

xあなたのことをするためにA2つのオプションがあります:

  1. ここでは使用しないautoでください:

    A x{ create() };
    
  2. ここではUniform初期化を使用しないでください。

    auto x(create());
    

それに加えて、あなたのコードには他に2つの問題があります。まず、適切なコピーコンストラクタの署名は次のようになります。

A(const A &) {printf("A CTOR by copy\n");}

さらに、関数からRValue参照を返すことはお勧めしません。代わりに、次のような値で返す必要があります。

A create(){
  A v;
  return v;   // std::move not needed here because C++11 compiler will put it for you here
}

あるいは単に:

A create(){
  return A();
}

編集:

ああ、そして単に政治的に正しいということは、 「普遍的な参照によるCTOR」A(A&&) ではありません。操作する抽象化のレベルに応じて、「移動によるCTOR」または「右辺値参照によるCTOR」になります。ユニバーサルリファレンスは常にテンプレートとその特定のタイプタイプの推論に関するものです。

別のコメントhttp://scottmeyers.blogspot.com/2012/10/copying-constructors-in-c11.htmlに添付したScottMeyersの記事も読んでください。ここでは、メモで参照しているのと同じC++の第一人者が正確に説明しています。あなたが直面する問題。お役に立てば幸いです。

于 2012-11-07T09:37:02.350 に答える
1

この線

auto x{ create() };//this does not compile

initializer_listのインスタンスではなくを作成します。Aたとえば、std::initializer_listを参照してください。

あなたが書くなら

A x{ create() };

コードがコンパイルされ、の型はxになりますA


A&&からは戻りません。Move Semantics and Compiler Optimizationscreate()を参照してください。これは Scott のスライドでも見たことがありません。


次のコードは出力のみです。こちらA CTORを参照してください。それはあなたが得ることができる最高のものです: オブジェクトを作成する必要があります. それとは別に、不要なコピー コンストラクターや代入演算子の呼び出しはありません。

#include <cstdio>
#include <utility>
using namespace std;

class A{
public:
    A(){         printf("A CTOR\n");}
    A(const A&) {printf("A CTOR by copy\n");}
    A(A&&){      printf("A CTOR by universal reverence\n");}
    A& operator=(const A& ) = delete;
};

A create(){
    return A();
}

int main() {
    A x{ create() };
    return 0;
}

std::move は、不要なコピーを取り除く唯一の方法ではありません。コンパイラはそれを行うことができます。たとえば、コピー省略と戻り値の最適化とは何ですか? を参照してください。または省略をコピーします

于 2012-11-07T09:34:25.733 に答える