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() 中的数据对象在函数完成时被销毁,但不应该先将它移动到 main 中的数据对象吗?

4

2 回答 2

15

这个功能:

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

返回对本地对象的引用,该对象将在调用返回时被销毁。因此,您的程序具有未定义的行为。因此,在此处调用move 构造函数时,返回的引用将悬空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 回答