C++ 函数返回包含输入容器特定元素的容器
我有一个C++ 函数返回包含输入容器特定元素的容器,c++,stl,copy,C++,Stl,Copy,我有一个向量或列表,其中我只想将代码应用于特定元素。例如 class Container : public std::vector<Element*> 我编写了一个成员函数Get(),如下所示 template<typename Fn> auto Container::Get(const Fn& fn) const { Container output; std::copy_if(cbegin(), cend(), std::inserter(o
向量
或列表
,其中我只想将代码应用于特定元素。例如
class Container : public std::vector<Element*>
我编写了一个成员函数Get()
,如下所示
template<typename Fn>
auto Container::Get(const Fn& fn) const {
Container output;
std::copy_if(cbegin(), cend(), std::inserter(output, output.end()), fn);
return output;
}
从性能角度看:这是一个好方法吗?还是复制和删除会更好
template<typename Fn>
auto Container::Get(const Fn& fn) const {
Container output(*this);
output.erase(std::remove_if(output.begin(), output.end(), fn), end(output));
return output;
}
模板
自动容器::Get(const-Fn&Fn)const{
容器输出(*此);
擦除(std::remove_if(output.begin()、output.end()、fn)、end(output));
返回输出;
}
还是有更好的方法
编辑:不同的例子
因为我前面的示例可以用更好的方式编写,所以让我们展示一个不同的示例:
while (!(container2 = container1.Get(IsSomething)).empty()&&TimesFooCalled<SomeValue)
{
Container container3(container2.Get(IsSomething));
if (!container3.empty()) {
Foo(*container3.BestElement());
} else {
Foo(*container2.BestElement());
}
}
while(!(container2=container1.Get(IsSomething)).empty()&&TimesFooCalled不回答您的直接问题,但请注意,您可以实现原始算法,而无需复制任何内容。如下所示:
bool found = false;
for (Element* const el: inputContainer) {
if (IsSomething(el)) {
found = true;
[some stuff]
}
}
if (!found) {
for (Element* const el : inputContainer) {
[some stuff]
}
}
for(auto const * item : inputContainer) if(IsSomething(item)) {
// Do stuff with item
}
inputContainer.erase(std::remove_if(std::begin(inputContainer), std::end(inputContainer),
[](Element const *item) {
if(IsSomething(item)) {
// Do something with item
return true;
}
return false;
}
));
不回答您的直接问题,但请注意,您可以在不复制任何内容的情况下实现原始算法。如下所示:
bool found = false;
for (Element* const el: inputContainer) {
if (IsSomething(el)) {
found = true;
[some stuff]
}
}
if (!found) {
for (Element* const el : inputContainer) {
[some stuff]
}
}
for(auto const * item : inputContainer) if(IsSomething(item)) {
// Do stuff with item
}
inputContainer.erase(std::remove_if(std::begin(inputContainer), std::end(inputContainer),
[](Element const *item) {
if(IsSomething(item)) {
// Do something with item
return true;
}
return false;
}
));
我通常使用的模式如下:
bool found = false;
for (Element* const el: inputContainer) {
if (IsSomething(el)) {
found = true;
[some stuff]
}
}
if (!found) {
for (Element* const el : inputContainer) {
[some stuff]
}
}
for(auto const * item : inputContainer) if(IsSomething(item)) {
// Do stuff with item
}
inputContainer.erase(std::remove_if(std::begin(inputContainer), std::end(inputContainer),
[](Element const *item) {
if(IsSomething(item)) {
// Do something with item
return true;
}
return false;
}
));
这通常已经足够好了,所以其他方法似乎有些过头了
为了获得更好的性能,最好不要从列表中复制或删除元素。根据我的经验,出于缓存原因,如果只查看一次列表,速度会更快。因此,下面是我将如何从列表中找到一个或另一个“最佳”值:
auto const isBetter = std::greater<Element>();
Element const * best = nullptr, const * alt_best = nullptr;
for(Element const * current : inputContainer) {
if(IsSomething(current)) {
if(!best || isBetter(*best, *current)) best = current;
} else {
if(!alt_best || isBetter(*alt_best, *current)) alt_best = current;
}
}
if(best) {
// do something with best
} else if(alt_best) {
// do something with alt_best
} else {
// empty list
}
我通常使用的模式如下:
bool found = false;
for (Element* const el: inputContainer) {
if (IsSomething(el)) {
found = true;
[some stuff]
}
}
if (!found) {
for (Element* const el : inputContainer) {
[some stuff]
}
}
for(auto const * item : inputContainer) if(IsSomething(item)) {
// Do stuff with item
}
inputContainer.erase(std::remove_if(std::begin(inputContainer), std::end(inputContainer),
[](Element const *item) {
if(IsSomething(item)) {
// Do something with item
return true;
}
return false;
}
));
这通常已经足够好了,所以其他方法似乎有些过头了
为了获得更好的性能,最好不要从列表中复制或删除元素。根据我的经验,出于缓存原因,如果只查看一次列表,速度会更快。因此,下面是我将如何从列表中找到一个或另一个“最佳”值:
auto const isBetter = std::greater<Element>();
Element const * best = nullptr, const * alt_best = nullptr;
for(Element const * current : inputContainer) {
if(IsSomething(current)) {
if(!best || isBetter(*best, *current)) best = current;
} else {
if(!alt_best || isBetter(*alt_best, *current)) alt_best = current;
}
}
if(best) {
// do something with best
} else if(alt_best) {
// do something with alt_best
} else {
// empty list
}
您需要back\u插入器output.end()
将在插入第一个元素后立即失效。如果您想要性能,我建议您选择Yes。它适用于任何提供push_-back
方法的东西。std::vector
和std::list
都可以。对容器进行子类化是一个好主意吗?我认为这不是一个好主意@JHBonarius请看我的扩展答案。您需要返回\u插入器输出。结束()
将在插入第一个元素后立即失效。如果您想要性能,我建议您选择Yes。它适用于任何提供push_-back
方法的东西。std::vector
和std::list
都可以。对容器进行子类化是一个好主意吗?我认为这不是一个好主意@JHBonarius请看我的延伸回答。