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

Hao*_*Shi 13 c++ tuples function c++11

我试图在我的函数中避免输出参数.旧功能是:

void getAllBlockMeanError(
    const vector<int> &vec, vector<int> &fact, vector<int> &mean, vector<int> &err)
Run Code Online (Sandbox Code Playgroud)

这里vec是输入参数,fact,meanerr输出参数.我试图将输出参数分组为一个元组:

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

现在我可以调用新函数:

tie(fact, mean, err) = getAllBlockMeanErrorTuple(vec);
Run Code Online (Sandbox Code Playgroud)

它对我来说看起来更干净.虽然我有一个问题,如何平等分配tie(fact, mean, err)工作?它是做深拷贝还是移动?因为fact,meanerrgetAllBlockMeanErrorTuple就会被破坏,我希望它做的举动,而不是深拷贝.

And*_*dyG 15

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

std::tie(fact, mean, err) = getAllBlockMeanErrorTuple(vec)
Run Code Online (Sandbox Code Playgroud)

应该将指派fact,meanerr.

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

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

输出:

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

请注意,该函数必须创建用于返回的向量的副本tuple,这可能不是您想要的.您可能希望std::move将元素分为std::make_tuple:

return make_tuple(std::move(fact), std::move(mean), std::move(err));
Run Code Online (Sandbox Code Playgroud)

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

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

auto[fact, mean, err] = getAllBlockMeanErrorTuple(vec);
Run Code Online (Sandbox Code Playgroud)

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

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

移动ctor
移动ctor

表明他们利用了copy-elision,这节省了额外的移动操作.


Jar*_*d42 12

std::tie(fact, mean, err) = getAllBlockMeanErrorTuple(vec);
Run Code Online (Sandbox Code Playgroud)

会做一个移动任务.

但正如评论中提到的那样

return make_tuple(fact, mean, err);
Run Code Online (Sandbox Code Playgroud)

会做一个副本,你可以解决这个问题:

return make_tuple(std::move(fact), std::move(mean), std::move(err));
Run Code Online (Sandbox Code Playgroud)