0

私はこの記事cppnextの暗黙の移動を読みましたが、この問題を理解していませんでした:

#include <iostream>
#include <vector>
struct X
{
    // invariant: v.size() == 5
    X() : v(5) {}

    ~X()
    {
        std::cout << v[0] << std::endl;
    }

 private:    
    std::vector<int> v;
};

int main()
{
    std::vector<X> y;
    y.push_back(X()); // X() rvalue: copied in C++03, moved in C++0x
}

MSVC2010では、実行時にバグはありません...誰か助けてもらえますか?

この記事には次の文があります:

ここでの重要な問題は、C ++ 03では、Xにはそのvメンバーが常に5つの要素を持つという不変条件があったことです。X ::〜X()はその不変条件を頼りにしましたが、新しく導入されたmoveコンストラクターはvから移動したため、その長さはゼロに設定されました。

vXを動かそうとしているので、長さがゼロになる理由がわかりません

4

4 に答える 4

1

MSVC2010は、自動生成されたmoveコンストラクターを実装していないため、コードで生成されたとしても、そこには表示されません。したがって、いつものように、「ランダムな実装XはYを実行しました」は、かなり意味のないステートメントです。

于 2012-05-29T10:45:20.787 に答える
1

Xを動かそうとしているので、vの長さがゼロになる理由がわかりません

まず第一に、push_back呼び出しで一時的なものを移動しようとはしません。移動するかX()、移動しません[*]。

(暗黙的に生成されたmoveコンストラクターを使用して)移動すると、そのデータメンバーvが移動されます。この記事の前提は、ベクトルから移動すると空のままになるということですが、それが必要なのか、それとも単なる典型的なのかは覚えていません。vただし、以前の要素にアクセスできることが保証されていない状態のままになることは確かです。

移動の全体的なポイントは、コピーに費用のかかるリソースをソースから転送することです。したがって、一時オブジェクトは、移動先がそれを取得したため、5要素の内部配列を持つことが保証されなくなりました。

MSVC 2010で機能する理由については、このコードが「微調整#1-デストラクタが暗黙的な移動を抑制する」のすぐ上の例として記事に示されていることを覚えておいてください。C ++ 11には、実際にはこの微調整が含まれています。ユーザー定義のデストラクタ(12.8 / 9)がある場合、暗黙の移動コンストラクタは生成されません。したがって、一時的なものは移動され、コピーされます。

[*]移動するか移動しないか、試行はありません。移動するかどうかは実装次第ではなく、標準で定義されています。

于 2012-05-29T10:17:52.470 に答える
1

この記事で説明しようとしている問題はX、push_backでを移動すると、不変条件が壊れることです。一時的なXベクトルvは移動後に空になるため、デストラクタ呼び出しは未定義の動作を呼び出します。コンパイラが移動セマンティクスを実装していないため、または未定義の動作が純粋な偶然による知覚可能なランタイムエラーを引き起こさないため、問題が発生しない可能性があります。

この動作は、Xインスタンスを明示的に移動するこの単純なプログラムで確認できます。

#include <vector>
#include <iostream>
struct X {
  X() : v(5) {}
  std::vector<int> v;
};

int main() {
  X x0;
  std::cout << x0.v.size() << ", ";
  X x1 = std::move(x0);
  std::cout << x0.v.size() << "\n";
}

GCC 4.7では、これらは

5、0

これは、暗黙的に生成std::vectorされたコンストラクターによって使用されるmoveコンストラクターに由来します。X直接確認できstd::vectorます:

int main() {
  std::vector<int> v0(5);
  std::cout << v0.size() << ", ";
  std::vector<int> v1 = std::move(v0);
  std::cout << v0.size() << "\n";
}

これにより、同じ出力が生成されます。

ここで、引用する例では、ユーザー定義のデストラクタが存在するということは、暗黙的に生成された移動コンストラクタXないため、で移動されないことを意味しpush_backます。

于 2012-05-29T10:09:18.147 に答える
0

VS2010では、一時的なものがコピーされ、後で破棄されます。移動セマンティクスでは、一時オブジェクトがベクトルに使用されるだけです。

于 2012-05-29T10:07:10.630 に答える