Return std::tuple 和移动语义/复制省略

Return std::tuple and move semantics / copy elision

我有以下工厂函数:

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();

真的需要吗?

In the return statement is vec considered an xvalue or prvalue and therefore moved or copy elided?

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

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

仍然返回一个左值。只是在复制省略不适用的情况下我们有 special rules that say that we just ignore the copy in this case when we're returning the name of an automatic object (and another 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;
}