如何在C++ 11中有效地返回大数据

Reg*_*gis 3 c++ return-value parameter-passing c++11

我真的很担心在C++ 11中返回大数据.什么是最有效的方式?这是我的相关功能:

void numericMethod1(vector<double>& solution,
                    const double input);

void numericMethod2(pair<vector<double>,vector<double>>& solution1,
                    vector<double>& solution2,
                    const double input1,
                    const double input2);
Run Code Online (Sandbox Code Playgroud)

这是我使用它们的方式:

int main()
{
    // apply numericMethod1
    double input = 0;
    vector<double> solution;
    numericMethod1(solution, input);

    // apply numericMethod2
    double input1 = 1;
    double input2 = 2;
    pair<vector<double>,vector<double>> solution1;
    vector<double> solution2;
    numericMethod2(solution1, solution2, input1, input2);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

问题是,std :: move()在后面的实现中是无用的吗?

执行:

void numericMethod1(vector<double>& solution,
                    const double input)
{
    vector<double> tmp_solution;

    for (...)
    {
    // some operation about tmp_solution
    // after that this vector become very large
    }

    solution = std::move(tmp_solution);
}

void numericMethod2(pair<vector<double>,vector<double>>& solution1,
                    vector<double>& solution2,
                    const double input1,
                    const double input2)
{
    vector<double> tmp_solution1_1;
    vector<double> tmp_solution1_2;
    vector<double> tmp_solution2;

    for (...)
    {
    // some operation about tmp_solution1_1, tmp_solution1_2 and tmp_solution2
    // after that the three vector become very large
    }

    solution1.first = std::move(tmp_solution1_1);
    solution1.second = std::move(tmp_solution1_2);
    solution2 = std::move(tmp_solution2);
}
Run Code Online (Sandbox Code Playgroud)

如果它们没用,我如何处理这些大的返回值而无需复制多次? 免费更改API!

UPDATE

感谢StackOverFlow和这些答案,在深入研究相关问题之后,我更了解这个问题.由于RVO,我更改了API,为了更清楚,我不再使用std :: pair.这是我的新代码:

struct SolutionType
{
    vector<double> X;
    vector<double> Y;
};

SolutionType newNumericMethod(const double input1,
                              const double input2);

int main()
{
    // apply newNumericMethod
    double input1 = 1;
    double input2 = 2;
    SolutionType solution = newNumericMethod(input1, input2);

    return 0;
}

SolutionType newNumericMethod(const double input1,
                              const double input2);
{
    SolutionType tmp_solution; // this will call the default constructor, right?
    // since the name is too long, i make alias.
    vector<double> &x = tmp_solution.X;
    vector<double> &y = tmp_solution.Y;

    for (...)
    {
    // some operation about x and y
    // after that these two vectors become very large
    }

    return tmp_solution;
}
Run Code Online (Sandbox Code Playgroud)

我怎么知道RVO发生了?或者我如何确保 RVO发生?

Vit*_*meo 9

按值返回,依赖于RVO(返回值优化).

auto make_big_vector()
{
    vector<huge_thing> v1;
    // fill v1

    // explicit move is not necessary here        
    return v1;
} 

auto make_big_stuff_tuple()
{
    vector<double> v0;
    // fill v0

    vector<huge_thing> v1;
    // fill v1

    // explicit move is necessary for make_tuple's arguments,
    // as make_tuple uses perfect-forwarding:
    // http://en.cppreference.com/w/cpp/utility/tuple/make_tuple

    return std::make_tuple(std::move(v0), std::move(v1));
}

auto r0 = make_big_vector();
auto r1 = make_big_stuff_tuple();
Run Code Online (Sandbox Code Playgroud)

我会将函数的API更改为仅按值返回.

  • @vitt返回引用有一个很大的优点:易于重用缓冲区.按值返回需要工作才能启用它. (2认同)