7

次のプログラムは、セグメンテーション違反でクラッシュします。

#include <iostream>
#include <vector>

using namespace std;

struct data
{
  data() : a(random()), b(random()), v({random(), random(), random()}) {}
  data(data&& m) noexcept : a(m.a), b(m.b), v(std::move(m.v)) { }

  long int a;
  long int b;
  std::vector<long int> v;
};

data&& randomize()
{
  srandom(time(0));
  data d;
  d.a = random();
  return std::move(d);
}

int main( int argc, char** argv )
{
  data d = randomize();
  cout << d.a << " " << d.b << endl;
  return 0;
}

コードは g++ バージョン 4.7.2 (Debian 4.7.2-5) でコンパイルされています。

g++ -std=c++11 -g test.cpp

私は何を間違っていますか?問題は std::vector 移動コンストラクターにあるようです。これがなくてもすべて正常に動作します。関数の終了時に randomize() からのデータ オブジェクトが破棄されているように見えますが、最初にメインのデータ オブジェクトに移動するべきではありませんか?

4

2 に答える 2

15

この機能:

data&& randomize()
{
    // ...
    data d
    // ...
    return std::move(d);
}

呼び出しが戻るときに破棄されるローカル オブジェクトへの参照を返します。したがって、プログラムにはUndefined Behaviorがあります。したがって、返された参照は、移動コンストラクターがここで呼び出されるまでにぶら下がります。data

data d = randomize();

typeのを返すdata必要があり、明示的に呼び出すべきではありませんstd::move():

data randomize()
{
    // ...
    data d
    // ...
    return d;
}

このようにして、コンパイラに(名前付き) 戻り値の最適化を実行する機会を与えることもできます。その結果、移動コンストラクターがまったく呼び出されない可能性があります。

于 2013-03-29T12:37:13.967 に答える
0

これは機能し、コンパイラの最適化に依存しないと思います:

data randomize()
{
    // ...
    data d
    // ...
    return std::move(d);
}

戻り値は、ローカル変数 d を破棄する前に構築する必要があります。

于 2013-03-29T17:23:41.797 に答える