通过右值引用传递并使用 std::move() 返回

Pass by rvalue reference and return using std::move()?

本文关键字:std move 返回 引用      更新时间:2023-10-16

考虑:

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

哪一个是首选(进程 1 或进程 2(?

这是否意味着在第一个示例 (process1( 中,如果我通过右值引用将对象传递给返回对象的函数,如果我不使用 std::move(),就会进行复制?

编译器:GCC 5.2.1

在第一个版本中

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

您将其作为右值引用传递,但通过"如果它有名称"启发式方法,它被视为函数中的左值,因此是复制 CTOR。

第二个版本使用std::move"重制"了一个右值(这正是它的意思(。因此,避免了复制 ctor。

期望移动不会比副本更昂贵是相当合理的,因此,鉴于现实生活中的情况归结为这一点,您可能更喜欢第二个版本。