移动std :: vector时的分段错误

时间:2013-03-29 12:35:07

标签: c++ c++11 g++ move-semantics

以下程序因segmention故障而崩溃:

#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()的数据对象会被破坏,但是它不应该首先移动到main中的数据对象吗?

2 个答案:

答案 0 :(得分:15)

此功能:

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

返回对本地对象的引用,该对象在调用返回时将被销毁。因此,您的程序具有未定义的行为。因此,在此处调用data的移动构造函数时,返回的引用将悬空

data d = randomize();

您应该返回data类型的,并且不应该明确调用std::move()

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

这样,您还将为编译器提供执行(Named) Return Value Optimization的机会,可能根本不会调用移动构造函数。

答案 1 :(得分:0)

我认为这会起作用,并且不依赖于编译器优化:

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

必须在销毁局部变量d之前构造返回值。