可能重复:
如何在C++中"返回一个对象"
我想知道以下三种方法之间是否存在差异:
void FillVector_1(vector<int>& v) {
v.push_back(1); // lots of push_backs!
}
vector<int> FillVector_2() {
vector<int> v;
v.push_back(1); // lots of push_backs!
return v;
}
vector<int> FillVector_3() {
int tab[SZ] = { 1, 2, 3, /*...*/ };
return vector<int>(tab, tab + SZ);
}
Run Code Online (Sandbox Code Playgroud)
Unc*_*ens 16
最大的区别是第一种方式附加到现有内容,而另外两种填充空向量.:)
我认为您正在寻找的关键字是返回值优化,这应该是相当普遍的(使用G ++,您必须专门关闭它以防止它被应用).也就是说,如果用法如下:
vector<int> vec = fill_vector();
Run Code Online (Sandbox Code Playgroud)
然后可能很容易就没有副本(而且功能更容易使用).
如果您正在使用现有向量
vector<int> vec;
while (something)
{
vec = fill_vector();
//do things
}
Run Code Online (Sandbox Code Playgroud)
然后使用out参数将避免在循环中创建向量并复制数据.
惯用的C++方法是通过使用输出迭代器来抽象容器类型:
template<typename OutputIterator>
void FillContainer(OutputIterator it) {
*it++ = 1;
...
}
Run Code Online (Sandbox Code Playgroud)
然后它可以与vector一起使用:
std::vector<int> v;
FillContainer(std::back_inserter(v));
Run Code Online (Sandbox Code Playgroud)
性能(以及其他优点,例如能够填充非空容器)与您的选项#1相同.另一个好处是,这可以用于以流模式输出,其中如果使用适当类型的迭代器(例如ostream_iterator),则立即处理并丢弃结果而不进行存储.
人们会认为参数是最好的,但实际上通常不是.这取决于编译器.一些编译器(我认为实际上是最新的编译器)将应用返回值优化 - Visual Studio 2005及更高版本应该在您提供的两种情况下都执行它(请参阅Visual C++ 2005中的命名返回值优化).
确切知道的最好方法是检查生成的反汇编.
在混合中添加第四个变体:
void FillVector_4(vector<int>& v) {
static const int tab[SZ] = {1,2,3, ... };
v.assign(tab,tab+SZ);
}
Run Code Online (Sandbox Code Playgroud)
如果您正在考虑性能版本2,则版本3 可能会使编译器vector<int>为返回值创建副本.也就是说,如果编译器不能做NRVO(命名返回值优化).此外,push_back没有a的连续s reserve可能导致一些重新分配,因为向量需要增长.这是否重要取决于您试图解决的问题.
您会很高兴知道C++ 0x将使返回本地创建的向量非常有效.我还建议阅读David Abrahams 关于有效价值类型的文章系列,包括传递/返回.