我有一个非常简单的问题:当我们使用向量std::vector<int>
作为函数的引用参数时,我们应该在调用函数之前调整向量大小还是调整函数内部的向量大小(假设大小为矢量可以在手前确定吗?我举了下面的例子来说明我的问题:
void fun1(std::vector<int> ¶)
{
para[0] = 1;
para[1] = 2;
....
para[10] = 11;
}
void fun2(std::vector<int> ¶)
{
para.resize(11);
para[0] = 1;
para[1] = 2;
...
para[10] = 11;
}
当我们调用fun1时,我们使用以下代码:
std::vector<int> mypara;
mypara.resize(11);
fun1(mypara);
当我们调用fun2时,我们使用以下代码:
std::vector<int> mypara;
fun2(mypara);
答案 0 :(得分:3)
只需使用push_back,让矢量在必要时自行调整大小:
std::vector<int> mypara;
mypara.push_back(1);
...
mypara.push_back(11);
如果您知道矢量中有多少元素,您可以在添加元素之前调用reserve
或将初始大小设置为参数:
std::vector<int> mypara(10);//Be aware that this will create 10 elements!
//or...
std::vector<int> mypara;
mypara.reserve(10);//This will set the size, but there won't be any elements in it yet.
对于大多数情况,矢量的初始大小足够大,并且不会经常调整大小。但有时,当您只添加一个元素并将其调整为更大的大小时,它可能会导致问题。在这种情况下,使用reserve也可以提高性能。
但是如果你需要进行大小调整,请在你的情况下在函数中执行。对代码的读者来说更清楚,可以看出你的意图。保持范围小。
答案 1 :(得分:3)
...你可能应该只返回矢量。
std::vector<int> fun3()
{
std::vector<int> para(11);
para[0] = 1;
para[1] = 2;
...
para[10] = 11;
return para;
}
我知道这感觉不对,但是C ++ / STL实际上对这类事情非常聪明。它实际上不会复制出para,它会做一个移动构造函数/返回值optomization而不是复制构造函数。
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
答案 2 :(得分:2)
两者都是正确的,虽然fun2似乎更安全一些。你可以将它复制到另一个项目,它可以正常工作,而不是fun1,它需要事先确定大小的大小。
答案 3 :(得分:2)
你根本不会明确resize
一个向量 - 既不在函数调用中也不在调用函数之前。 vector
管理自己的内存使用量,并根据需要增长以容纳新元素。
在某些情况下,您将添加鬃毛元素,并且由于性能原因,不希望遭受向量的多次重新分配。这通常只发生在应用程序的“热路径”中,而不是每个应用程序。在这些相对罕见的场景中,添加元素的功能应该负责启动向量中有足够的容量。为此,您不要使用resize
,而是使用reserve
。两者都将重新分配vector
如果必要(并因此使迭代器无效,请注意),但resize
实际上同时更改了size()
的{{1}}和capacity()
,而vector
仅更改reserve
。
了解差异:
capacity()
上述内容不会输出任何内容,因为vector <int> v;
v.reserve (10);
copy (v.begin(), v.end(), ostream_iterator (cout, ","));
中没有任何内容,即使有10个元素也有空间。但是:
vector
此代码将输出10个默认构造的vector <int> v;
v.resize (10);
copy (v.begin(), v.end(), ostream_iterator (cout, ","));
s。数组中有10个元素。如果您int
resizing()
只是为新元素腾出空间,vector
可能不是您想要做的。
答案 4 :(得分:1)
如果你的函数对输入向量有要求,不使用它的数据,并假设它是可覆盖的,那么简单地按值返回向量可能更好:
std::vector<int> fun()
{
std::vector<int> v(11);
std::iota(v.begin(), v.end(), 1);
return v;
}
这样,调用者不必担心输入向量的状态必须是什么,并且该函数不必对向量进行任何检查。
答案 5 :(得分:1)
我想如果你能在运行时知道你现在需要的大小,你应该调用resize。为什么?因为这样可以防止多次大小增加和复制的开销......
所以,当你知道大量的插入将要发生时,你的函数中的答案就是......所以你想立即做到这一点......