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

Tar*_*ani 10 c++ move-semantics c++17

我有以下工厂功能:

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();
Run Code Online (Sandbox Code Playgroud)

在退货声明被vec认为是xvalueprvalue因此移动或复制被删除?

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

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

auto [b, vec] = factory();
Run Code Online (Sandbox Code Playgroud)

这真的需要吗?

Bar*_*rry 14

在return语句中被vec视为xvalue或prvalue,因此移动或复制是否被删除?

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

std::vector<int> factory() {
    std::vector<int> vec;
    return vec;
}
Run Code Online (Sandbox Code Playgroud)

仍然是一个左值.只是我们有一些特殊的规则,说我们在这种情况下只是在我们返回自动对象的名称时忽略副本(在复制省略不适用的情况下另一个特殊规则,但我们仍然试图从左右移动).

但这些特殊规则适用于return object;案件,它们不适用于return {1, object};案件,无论它看起来多么相似.在你的代码中,这会做一个副本,因为这就是你要求的.如果你想搬家,你必须做:

return {1, std::move(object)};
Run Code Online (Sandbox Code Playgroud)

为了避免搬家,你必须做到:

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;
}
Run Code Online (Sandbox Code Playgroud)

  • @Aconcagua我的目标不是代码高尔夫. (3认同)