2013-03-29 31 views
5

下面的程序崩溃,并segmention故障:段故障时的std ::矢量

#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; 
} 

的代码被编译以克++版本4.7.2(Debian的4.7.2-5):

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

我做错了什么?这个问题似乎是在std :: vector移动构造函数,导致一切正常工作没有它。看起来来自randomize()的数据对象在函数完成时会被销毁,但不应该将它移动到主数据对象中吗?

+3

请注意,这里不需要返回* rvalue *引用(即使它有效返回对本地自动变量的引用)。如果可能的话,函数返回值总是被移动。 –

回答

13

此功能:

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,可能导致在没有呼叫到移动构造的。

+0

感谢您的回答!但是这种优化是否总是由gcc执行,还是有一些例外? –

+0

@PavelDavydov:不客气:)完全取决于编译器来决定,而且你不应该依赖这个elision是否被执行的假设。你无法分辨。但是,在这种情况下,会发生什么情况是,如果具有足够高的优化级别,则任何编译器都应该调用移动构造函数。但是,这绝不是你应该依赖的东西。 –

0

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

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

则返回值的局部变量d的破坏之前建造。