从班级移动矢量,返回&&或进入临时?

时间:2014-02-12 20:51:58

标签: c++ c++11 vector move-semantics

class EntityFactory
{
public:
    EntityFactory(tinyxml2::XMLElement * pEntitiesNode);
    ~EntityFactory();

    std::vector< std::unique_ptr<Entity> > && TakeEntities();

protected:
    std::vector< std::unique_ptr<Entity> > mEntities;
};

当我调用TakeEntity时,我想将mEntities向量移到此类之外。

我应该返回我搬入的临时变量还是返回&amp;&amp;?

std::vector< std::unique_ptr<Entity> > && EntityFactory::TakeEntities()
    {
    return std::move(mEntities);
    }

//or
std::vector< std::unique_ptr<Entity> > EntityFactory::TakeEntities()
    {
    return std::move(mEntities);
    }

我想要的最终结果是我可以从其他地方调用此函数,并将字段向量移动到调用站点附近的变量中。

3 个答案:

答案 0 :(得分:4)

正确的方法可能是按值返回只有在实例可移动时才会这样做:

class Foo
{
    std::unique_ptr<Bar> bar_;

public:
    std::unique_ptr<Bar> get_bar() &&
    {
        return std::move(bar_);
    }
};

这样,如果整个实例本身过期,您只能从该成员移动。一般来说,没有必要返回一个右值参考,因为这样可以获得很少的收益,而且通常不会保证安全。例如,假设您有Foo f();,请考虑:

auto && p = f().get_bar();

如果按值返回,这是安全的,但如果您通过引用返回,则会成为悬空引用。

答案 1 :(得分:1)

如果禁用编译器copy elision,请使用第一个,因为第二个将生成一个额外的临时变量,这会降低性能。

如果你没有禁用copy/move elision,它们很可能是相同的(性能)。

答案 2 :(得分:0)

您不应该返回右值引用,并且可能会定义一个合适的实体:

#include <iostream>
#include <vector>

struct Entity {
    int value;
    Entity() {
        static int n;
        value = ++n;
    }

    Entity(Entity&&) = default;
    Entity& operator = (Entity&&) = default;

    Entity(const Entity&) = delete;
    Entity& operator = (const Entity&) = delete;
};

class EntityFactory
{
    public:
    EntityFactory() {};

    void insert(Entity&& entity) {
        return mEntities.push_back(std::move(entity));
    }

    std::vector<Entity> Entities() {
        return std::move(mEntities);
    }

    protected:
    std::vector<Entity> mEntities;
};

int main() {
    EntityFactory factory;
    factory.insert(Entity());
    factory.insert(Entity());
    factory.insert(Entity());
    std::vector<Entity> entities = factory.Entities();
    for(const auto& e: entities) {
        std::cout << e.value;
    }
    std::cout << std::endl;
    if(factory.Entities().empty())
        std::cout << "Empty factory\n";
}

目标(获取函数调用结果的值)将是复制省略值或rvalue构造值。