您应该按价值返回。
该标准具有特定的功能,可以提高按价值返回的效率。它被称为“复制省略”,在这种情况下更具体地称为“命名返回值优化(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
是反复调用向量,则此基于模板的代码应该同样出色。
f
怎么样?