C++ 移动std::vector时出现分段错误

C++ 移动std::vector时出现分段错误,c++,c++11,g++,move-semantics,C++,C++11,G++,Move Semantics,以下程序因分段错误而崩溃: #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)) { }

以下程序因分段错误而崩溃:

#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;
}
我做错了什么?问题似乎出在std::vector move构造函数中,因为没有它一切都可以正常工作。函数完成时,来自randomize()的数据对象似乎已被销毁,但它不应该首先移动到main中的数据对象吗?

此函数:

data&& randomize()
{
    // ...
    data d
    // ...
    return std::move(d);
}
返回对本地对象的引用,该对象将在调用返回时被销毁。因此,您的程序具有未定义的行为。因此,在此处调用
data
的move构造函数时,返回的引用将处于悬空状态:

data d = randomize();
您应该返回类型为
data
的值,并且不应该显式调用
std::move()


通过这种方式,您还将给编译器执行的机会,可能导致根本不调用move构造函数。

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

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

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

请注意,此处不需要返回右值引用(即使返回对局部自动变量的引用是有效的)。如果可能的话,函数返回值总是被移动的。谢谢你的回答!但是这种优化总是由gcc执行,还是会有一些例外?@PavelDavydov:不客气:)这完全取决于编译器的决定,你永远不应该依赖于这种省略是否执行的假设。你就是说不出来。然而,在这种情况下,如果优化级别足够高,任何编译器都应该省略对move构造函数的调用。但是,这也不是你应该依赖的。你提供的解决方案在C++11中通常是无效的。使用已删除的复制构造函数,它将不会编译。
data randomize()
{
    // ...
    data d
    // ...
    return d;
}
data randomize()
{
    // ...
    data d
    // ...
    return std::move(d);
}