你应该按价值返回。
该标准具有提高按价值退货效率的特定功能。它被称为“复制省略”,在这种情况下更具体地说是“命名返回值优化 (NRVO)”。
编译器不必实现它,但是编译器也不必实现函数内联(或根本执行任何优化)。但是,如果编译器不进行优化,标准库的性能可能会很差,并且所有严肃的编译器都实现了内联和 NRVO(以及其他优化)。
应用 NRVO 时,以下代码不会有复制:
std::vector<int> f() {
std::vector<int> result;
... populate the vector ...
return result;
}
std::vector<int> myvec = f();
但用户可能想要这样做:
std::vector<int> myvec;
... some time later ...
myvec = f();
复制省略不会阻止此处的复制,因为它是赋值而不是初始化。但是,您仍然应该按值返回。在 C++11 中,赋值被不同的东西优化,称为“移动语义”。在 C++03 中,上面的代码确实会导致复制,虽然理论上优化器可能能够避免它,但实际上它太难了。因此myvec = f()
,在 C++03 中,您应该这样编写:
std::vector<int> myvec;
... some time later ...
f().swap(myvec);
还有另一种选择,即为用户提供更灵活的界面:
template <typename OutputIterator> void f(OutputIterator it) {
... write elements to the iterator like this ...
*it++ = 0;
*it++ = 1;
}
然后,您还可以在此基础上支持现有的基于矢量的界面:
std::vector<int> f() {
std::vector<int> result;
f(std::back_inserter(result));
return result;
}
如果您现有的代码以比预先固定数量更复杂的方式使用,这可能比您现有的代码效率低。reserve()
但是如果你现有的代码基本上是重复调用push_back
向量,那么这个基于模板的代码应该也一样好。