Reg*_*gis 9 c++ return-value parameter-passing return-value-optimization c++11
这个问题是由C++ 11中关于RVO的混淆引发的.
我有两种方法来"返回"值:返回通过值和通过引用参数返回.如果我不考虑性能,我更喜欢第一个.由于按值返回更自然,我可以轻松区分输入和输出.但是,如果我在回归大数据时考虑效率.我无法决定,因为在C++ 11中,有RVO.
这是我的示例代码,这两个代码执行相同的工作:
按价值返回
struct SolutionType
{
vector<double> X;
vector<double> Y;
SolutionType(int N) : X(N),Y(N) { }
};
SolutionType firstReturnMethod(const double input1,
const double input2);
{
// Some work is here
SolutionType tmp_solution(N);
// 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)
通过参考参数返回
void secondReturnMethod(SolutionType& solution,
const double input1,
const double input2);
{
// Some work is here
// since the name is too long, I make alias.
vector<double> &x = solution.X;
vector<double> &y = solution.Y;
for (...)
{
// some operation about x and y
// after that these two vectors become very large
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的问题:
更新 感谢这些答案,我知道第一种方法在大多数方面都更好.
这是一些有用的相关链接,可以帮助我理解这个问题:
Ser*_*eyA 16
首先,您所做的正确技术术语是NRVO.RVO与被退回的临时工具有关:
X foo() {
return make_x();
}
Run Code Online (Sandbox Code Playgroud)
NRVO引用返回的命名对象:
X foo() {
X x = make_x();
x.do_stuff();
return x;
}
Run Code Online (Sandbox Code Playgroud)
其次,(N)RVO是编译器优化,并非强制要求.但是,您可以非常肯定,如果使用现代编译器,(N)RVO将会非常积极地使用.
第三,(N)RVO 不是 C++ 11的功能 - 它早在2011年就已存在.
最重要的是,你在C++ 11中拥有的是一个移动构造函数.因此,如果您的类支持移动语义,即使(N)RVO没有发生,它也会被移动而不是被复制.不幸的是,并非一切都可以在语义上有效地移动.
第五,通过引用返回是一个可怕的反模式.它确保对象将被有效地创建两次 - 第一次作为"空"对象,第二次填充数据时 - 它使您无法使用"空"状态不是有效不变量的对象.