返回std :: tuple并移动语义/复制省略

时间:2018-07-25 14:09:23

标签: c++ c++17 move-semantics

我具有以下工厂功能:

auto factory() -> std::tuple<bool, std::vector<int>>
{
    std::vector<int> vec;
    vec.push_back(1);
    vec.push_back(2);

    return { true, vec };
}

auto [b, vec] = factory();

在return语句中,vec被认为是xvalueprvalue,因此被移动或复制了吗?

我的猜测不是,因为编译器在对return语句中的std::tuple进行列表初始化时,仍然不知道vec将被销毁。所以也许需要显式的std :: move:

auto factory() -> std::tuple<bool, std::vector<int>>
{
    ...
    return { true, std::move(vec) };
}

auto [b, vec] = factory();

真的需要吗?

1 个答案:

答案 0 :(得分:12)

  

在return语句中,vec被认为是xvalue或prvalue,因此被移动或复制了吗?

vec总是 一个左值。即使在简单的情况下:

std::vector<int> factory() {
    std::vector<int> vec;
    return vec;
}

still 返回左值。只是我们有special rules表示在这种情况下,当我们返回自动对象的名称时,我们将忽略该副本(在不使用复制省略的情况下,另一个special rule ,但我们仍然尝试从左值移开。)

但那些特殊规则仅适用于return object;情况,无论外观多么相似,都不适用于return {1, object};情况。在这里的代码中,它将进行复制,因为这就是您要的。如果要移动,必须执行以下操作:

return {1, std::move(object)};

为了避免移动,您必须执行以下操作:

auto factory() -> std::tuple<bool, std::vector<int>>
{
    std::tuple<bool, std::vector<int>> t;

    auto& [b, vec] = t;
    b = true;
    vec.push_back(1);
    vec.push_back(2);
    return t;
}