函数返回由向量

时间:2016-09-15 14:49:51

标签: c++ function c++11 tuples

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

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)的平等分配如何运作?它是做深拷贝还是移动?由于fact中的meanerrgetAllBlockMeanErrorTuple将会被销毁,我希望它会移动而不是深层复制。

2 个答案:

答案 0 :(得分:14)

你的功能签名是tuple< vector<int>, vector<int>, vector<int> >,这是一个临时的,元素有资格被移动,所以

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

应移动 - 分配factmeanerr

以下是您自己查看的示例程序(demo):

#include <iostream>
#include <vector>
#include <tuple>

struct A
{
    A() = default;
    ~A() = default;
    A(const A&)
    {
        std::cout << "Copy ctor\n";
    }
    A(A&&)
    {
        std::cout << "Move ctor\n";
    }
    A& operator=(const A&)
    {
        std::cout << "Copy assign\n";
        return *this;
    }
    A& operator=(A&&)
    {
        std::cout << "Move assign\n";
        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));

Here's the same example as above, but with std::move used in make_tuple

请注意,使用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中有一些支持:{{3 (谢谢,@ Revolver_Ocelot)

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

  

移动ctor
  移动ctor

表示他们利用了copy-elision,这可以节省额外的移动操作。

答案 1 :(得分:12)

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