仍然可以移动按值返回的const对象吗?

时间:2017-03-25 17:11:56

标签: c++

示例:

Foo return_a_foo()
{
    const auto a_foo = make_a_foo();

    //Work with, but do not mutate a_foo...

    return a_foo;       
}

如果编译器不能使用RVO,我至少会期望它尝试移动a_foo。但是,a_foo是const(但仍然要超出范围)。它是否在标准的任何地方都说100%保证不移动(无赖)或者是实现定义?

2 个答案:

答案 0 :(得分:4)

  

仍然可以移动按值返回的const对象吗?

有些人会惊讶地得知答案是“有时是的”。

但是,您必须为它们提供更多构造函数才能启用此功能。您还必须要么成员mutable,要么手动处理const-move-construction。

证明:

#include <iostream>
#include <memory>

struct Foo
{
    Foo() { std::cout << "default c'tor\n"; }
    Foo(Foo const&&) { std::cout << "Foo const&&\n"; }
    Foo(Foo &&) { std::cout << "Foo &&\n"; }
    Foo(Foo const&) { std::cout << "Foo const&\n"; }
    Foo(Foo &) { std::cout << "Foo &\n"; }

};

const Foo make_a_foo()
{
    auto p = std::make_unique<const Foo>();
    return std::move(*p);
}

const Foo return_a_foo()
{
    const auto a_foo = make_a_foo();

    //Work with, but do not mutate a_foo...

    return a_foo;
}

int main()
{
    auto f = return_a_foo();
}

示例输出:

default c'tor
Foo const&&

答案 1 :(得分:2)

不,const T无法绑定到非常量T&&,因此a_foo无法移动。

您的函数返回非const Foo,因此a_foo将被复制到返回值。然后可以移动返回值,因为它是非常量的。请参阅this example

实际上,所有这些副本和动作都可能被删除。