我有一个有两个矢量参数的函数。它只需要“输入向量”中的一些元素,并将它们添加到“输出向量”中。它看起来像这样:
void foo(const std::vector< MyObj >& myObjsIn, std::vector< MyObj >& myObjsOut)
{
for (size_t i = 0; i < myObjsIn.size(); i++)
{
if (myObjsIn[i].condition())
{
myObjsOut.push_back(myObjsIn[i]);
}
}
}
但如果我给出与输入和输出相同的向量(它在向量的末尾添加所选元素),则存在一个错误。如果我添加清除输出一个,它将清除输入一个(对于指定的情况);所以我得到一个空的矢量。我想到了:
void foo(const std::vector< MyObj >& myObjsIn, std::vector< MyObj >& myObjsOut)
{
std::vector< MyObj > tmpObjs = myObjsIn;
myObjsOut.clear();
for (size_t i = 0; i < tmpObjs.size(); i++)
{
if (tmpObjs[i].condition())
{
myObjsOut.push_back(tmpObjs[i]);
}
}
}
但是可以将输入向量复制到临时向量并清除输出向量吗?是否更好地返回输出向量并创建一个临时向量来添加所选元素?像这样:
std::vector< MyObj > foo(const std::vector< MyObj >& myObjsIn)
{
std::vector< MyObj > tmpObjs;
for (size_t i = 0; i < myObjsIn.size(); i++)
{
if (tmpObjs[i].condition())
{
tmpObjs.push_back(myObjsIn[i]);
}
}
return tmpObjs;
}
或者您建议我做什么,修复该错误并优化我的代码?
答案 0 :(得分:2)
如果您坚持使用单一用途的功能,那么您的最终答案似乎非常合理。然而另一种选择是临时交换:
void foo(const std::vector< MyObj >& myObjsIn, std::vector< MyObj >& myObjsOut)
{
std::vector< MyObj > tmpObjs;
for (size_t i = 0; i < myObjsIn.size(); i++)
{
if (myObjsIn[i].condition())
{
tmpObjs.push_back(myObjsIn[i]);
}
}
myObjsOut.swap(tmpObjs);
}
可能更优雅的解决方案是利用boost::filter_iterator
(http://www.boost.org/doc/libs/1_55_0/libs/iterator/doc/filter_iterator.html),然后您可以在ranged-constructor中使用两个过滤器迭代器到新的vector
。
(未经测试的)代码看起来像这样(当我得到片刻时会尝试编译):
struct execute_condition
{
bool operator()(const MyObj& obj) const { return obj.condition(); }
};
std::vector filtered_objects(boost::make_filter_iterator<execute_condition>(myObjsIn.begin(), myObjsIn.end()), boost::make_filter_iterator<execute_condition>(myObjsIn.end(), myObjsIn.end()));
答案 1 :(得分:0)
由于您在输出向量上调用push_back,因此您应该更改的唯一内容是循环中的停止条件,因此您将消除无限运行并保持原始功能
void foo(const std::vector< MyObj >& myObjsIn, std::vector< MyObj >& myObjsOut)
{
size_t inSize = myObjsIn.size();
for (size_t i = 0; i < inSize; i++)
{
if (myObjsIn[i].condition())
{
myObjsOut.push_back(myObjsIn[i]);
}
}
}