函数返回一个由向量组成的元组

Function return a tuple made of vectors

本文关键字:向量 元组 一个 返回 函数      更新时间:2023-10-16

我正在努力避免函数中的输出参数。旧功能是:

void getAllBlockMeanError(
    const vector<int> &vec, vector<int> &fact, vector<int> &mean, vector<int> &err)

这里vec是输入自变量,factmeanerr是输出自变量。我试图将输出参数分组为一个元组:

tuple< vector<int>, vector<int>, vector<int> > 
                                  getAllBlockMeanErrorTuple(const vector<int> &vec)
{
    vector<int> fact, mean, err;
    //....
    return make_tuple(fact, mean, err);
}

现在我可以用调用新函数

tie(fact, mean, err) = getAllBlockMeanErrorTuple(vec);

在我看来它更干净。虽然我有一个问题,tie(fact, mean, err)的相等分配是如何工作的?它是深度复制还是移动?由于getAllBlockMeanErrorTuple中的factmeanerr将被销毁,我希望它是在移动而不是深度复制。

您的函数签名是tuple< vector<int>, vector<int>, vector<int> >,这是一个临时的,元素可以被移动,所以

std::tie(fact, mean, err) = getAllBlockMeanErrorTuple(vec)

应移动分配factmeanerr

这里有一个示例程序供您自己查看(演示(:

#include <iostream>
#include <vector>
#include <tuple>
struct A
{
    A() = default;
    ~A() = default;
    A(const A&)
    {
        std::cout << "Copy ctorn";
    }
    A(A&&)
    {
        std::cout << "Move ctorn";
    }
    A& operator=(const A&)
    {
        std::cout << "Copy assignn";
        return *this;
    }
    A& operator=(A&&)
    {
        std::cout << "Move assignn";
        return *this;
    }
};
std::tuple<A, A> DoTheThing()
{
    A first;
    A second;
    return std::make_tuple(first, second);
}
int main()
{
    A first;
    A second;
    std::tie(first, second) = DoTheThing();
}

输出:

复制ctor
复制ctor
移动分配
移动分配

请注意,函数必须创建向量的副本才能返回tuple,这可能不是您想要的。您可能想要将元素std::move转换为std::make_tuple:

return make_tuple(std::move(fact), std::move(mean), std::move(err));

这是与上面相同的例子,但在make_tuple 中使用了std::move

请注意,使用C++17的结构化绑定,您可以完全忘记使用std::tie,而更多地依赖auto(谢谢,@Yakk(:

auto[fact, mean, err] = getAllBlockMeanErrorTuple(vec);

clang(3.8.0(和gcc(6.1.0(的C++17标准的早期实现还不支持它,但clang 4.0.0中似乎有一些支持:Demo(谢谢,@Revolver_Ocelot(

您会注意到,具有结构化绑定的输出更改为:

移动ctor
移动ctor

表示它们利用了拷贝省略,从而节省了额外的移动操作。

std::tie(fact, mean, err) = getAllBlockMeanErrorTuple(vec);

会做搬家作业。

但正如评论中提到的那样

return make_tuple(fact, mean, err);

你可以用来解决这个问题

return make_tuple(std::move(fact), std::move(mean), std::move(err));