2016-02-13 70 views
2

考慮:傳遞rvalue引用並使用std :: move()返回?

struct Foo { 
    Foo()      { std::cout << "default ctor" << std::endl; } 
    Foo (const Foo&)   { std::cout << "copy ctor" << std::endl; } 
    Foo& operator= (const Foo&) { std::cout << "copy op" << std::endl; return *this; } 
    Foo (Foo&&)     { std::cout << "move ctor" << std::endl; } 
    Foo& operator= (Foo&&)  { std::cout << "move op" << std::endl; return *this; } 
    ~Foo()      { std::cout << "dtor" << std::endl; } 
}; 


Foo process1 (Foo&& foo) { 
    return foo; 
} 


Foo process2 (Foo&& foo) { 
    return std::move (foo); 
} 

與用法:

Foo foo {}; 
foo = process1 (std::move (foo)); 

給出了結果:

default ctor 
copy ctor 
move op 
dtor 
dtor 

與用法:

Foo foo {}; 
foo = process2 (std::move (foo)); 

給出了結果:

default ctor 
move ctor 
move op 
dtor 
dtor 

哪一個是首選的(process1或process2)?

這是否意味着在第一個示例(process1)中,如果我通過右函數的參數傳遞對象,該函數將返回一個Object,如果我不使用std::move()

編譯器:GCC 5.2.1

回答

6

在第一個版本

Foo process1 (Foo&& foo) { 
    return foo; 
} 

你把它作爲一個右值參考,而是由"if it has a name" heuristic,它被當作函數內的左值,因此複製ctor。

第二個版本使用std::move(這正是它的意思)「重製」這個右值。因此避免了拷貝。

期待移動不會比副本更昂貴是非常合理的,因此,考慮到現實生活中的情況,您可能更喜歡第二個版本。