我们说我有这个非常简单的代码:
std::vector<int> getVector( int size )
{
std::vector<int> res;
for ( size_t i = 0; i != size; ++i )
res.push_back( i* 23 );
return res;
}
int main ()
{
std::vector<int> v;
v = getVector(10);
std::cout << "Size1 is " << v.size() << std::endl;
v = getVector(15);
std::cout << "Size2 is " << v.size() << std::endl;
}
输出:
Size1是10
Size2是15
现在,让我们说我想要更改getVector
以避免无用的对象副本并优化速度和内存使用。因此,getVector
现在将获得对要填充的向量的引用。
void getVector( int size, std::vector<int>& res )
{
for ( size_t i = 0; i != size; ++i )
res.push_back( i* 23 );
}
现在,如果我改变主要功能,而不注意:
int main ()
{
std::vector<int> v;
getVector(10,v);
std::cout << "Size1 is " << v.size() << std::endl;
getVector(15,v);
std::cout << "Size2 is " << v.size() << std::endl;
}
输出:
Size1是10
Size2是25
这不是我原来的。
我已经完成了这种改变(用参考传递的对象取代了返回值)的时间音调,而且我一直在问自己同样的问题:谁应该清除向量?
是否有任何&#34; guidline&#34;或者&#34;一般规则&#34;在这种情况下说谁应该清除矢量?
该功能本身应该这样做吗?
void getVector( int size, std::vector<int>& res )
{
res.clear();
for ( size_t i = 0; i != size; ++i )
res.push_back( i* 23 );
}
或者来电者应该这样做吗?
int main ()
{
std::vector<int> v;
getVector(10,v);
std::cout << "Size1 is " << v.size() << std::endl;
v.clear();
getVector(15,v);
std::cout << "Size2 is " << v.size() << std::endl;
}
修改
如许多人所报告的那样,例子可能是错误选择,因为它是一个错误的优化&#34;但是可能存在这样的情况:通过引用检索向量并且问题仍然存在。例如:
bool hasData( std::vector<int>& retrievedData );
或
void splitVector( const std::vector<int>& originalVector,
std::vector<int>& part1,
std::vector<int>& part2 );
...
答案 0 :(得分:4)
现在,让我们说我想改变getVector以避免无用的对象 复制并优化速度和内存使用。所以getVector现在会得到 对要填充的向量的引用。
你应该考虑一些事情:
vector::reserve
函数的开头使用getVector
优化此代码段。答案 1 :(得分:2)
在第一个例子中,该函数被称为&#34; getVector&#34;这适合描述函数的作用。它返回一个具有一定数量元素的向量,如预期的那样。
在第二个例子中,同样不适用。该函数仍被称为&#34; getVector&#34;但现在你要清除矢量。它不再描述函数,因为您将向量传递给它并使用它做事。它更像是&#34; takeAVectorClearItAndInitializeIt&#34;。而且您可能不想命名这样的函数或在代码中使用它。 (当然,我夸大了一点,但你明白了)
为了使函数易于理解,它应该有一个清晰的函数,而不是在后台做隐藏的事情(比如清除客户端的向量)。如果我要使用你的功能,我可能会对为什么我的矢量被清除感到困惑。
通常它是负责管理自己的变量的客户端代码。即使客户端代码调用一个函数来清除向量,责任仍然在客户端代码中,以清除其向量。在您的情况下,您从客户端代码知道&#34; getVector&#34;函数是因为你把它们都放在一起所以它不会让你感到困惑,但是当你编写的代码只需要两个函数中的一个时(清除OR初始化),你可能会做一些影响所有使用这个函数的代码并创建更多的代码。问题。
更具体地回答您的问题。
如果你不想复制通过引用的向量,可以将函数命名为更具描述性的函数,例如&#34; initializeVector&#34;这样你就可以更清楚自己在做什么了。
你通常应该打电话给&#39;清除&#39;从客户端代码来看,所以你的第一个例子会更好,直到遇到性能问题。 (当你获得不同的向量时,明确是隐含的)
答案 2 :(得分:1)
没有单身权利。但是想一下stringstream类对象以供参考。打算重用此类对象的人需要在重用对象之前进行清理。创建对象的人通常负责删除对象。
答案 3 :(得分:0)
两者都没有。相反,您应该重新考虑您的设计决策。您为消除(可能是理论上的)性能问题而执行的操作 - 我从您的措辞中读到了这个
避免无用的对象副本并优化速度和内存使用
取代了两个具体问题:
std::vector
吗?相对容易回答,是一个抽象而又难以回答的问题,但它会给你(和我们)带来严重的麻烦:你的“优化”实际上会导致性能下降