- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
这可能是 STL 中命名最差的函数吗? (反问)
std::remove_copy_if() 实际上似乎没有进行任何删除。据我所知,它的行为更像是 copy_if_not。
否定有点令人困惑,但可以使用 std::not1() 解决,但是我可能会误解一些东西,因为我无法理解这个函数与删除有什么关系 - 我错过了什么吗?
如果没有,是否有 STL 算法用于有条件地从容器中移除(移动?)元素并将它们放入另一个容器中?
编辑以添加示例,以免读者感到困惑。
以下程序似乎未触及输入范围 (V1):
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
using std::cout;
using std::endl;
int main (void)
{
std::vector<int> V1, V2;
V1.push_back(-2);
V1.push_back(0);
V1.push_back(-1);
V1.push_back(0);
V1.push_back(1);
V1.push_back(2);
std::copy(V1.begin(), V1.end(), std::ostream_iterator<int>(cout, " "));
cout << endl;
std::remove_copy_if(
V1.begin(),
V1.end(),
std::back_inserter(V2),
std::bind2nd(std::less<int>(), 0));
std::copy(V2.begin(), V2.end(), std::ostream_iterator<int>(cout, " "));
cout << endl;
std::copy(V1.begin(), V1.end(), std::ostream_iterator<int>(cout, " "));
cout << endl;
}
它输出:
-2 0 -1 0 1 2
0 0 1 2
-2 0 -1 0 1 2
我期待所以看到类似的东西:
-2 0 -1 0 1 2
0 0 1 2
0 0 1 2 ? ? ?
在哪里?可以是任何值。但令我惊讶的是,输入范围没有被触及,并且返回值不能与(在这种情况下)std::vector::erase() 一起使用。 (返回值是一个输出迭代器。)
最佳答案
Could this be the worst named function in the STL?
一些背景信息:在标准库(或原始 STL)中,存在三个概念,容器、容器中的迭代器以及应用于迭代器的算法。迭代器用作范围元素的游标和访问器,但没有对容器的引用(如前所述,甚至可能没有底层容器)。
这种分离具有很好的特性,您可以将算法应用于不属于容器的元素范围(考虑迭代器适配器,如 std::istream_iterator
或 std::ostream_iterator
) 或属于容器的那个不考虑所有元素 (std::sort( v.begin(), v.begin()+v.size()/2 )
缩短容器的前半部分)。
不利的一面是,因为算法(和迭代器)并不真正了解容器,他们无法真正修改它,他们只能修改存储的元素(这是他们可以访问的)。变异算法,如 std::remove
或 std::remove_if
在此前提下工作:它们有效地覆盖与条件不匹配的元素删除 它们来自容器,但它们不修改容器,只修改包含的值,这取决于 erase-remove 习惯用法的第二步中的调用者:
v.erase( std::remove_if( v.begin(), v.end(), pred ),
v.end() );
此外,对于变异算法(那些执行更改的算法),例如 std::remove
有一个通过在名称中添加 copy
来命名的非变异版本: std::remove_copy_if
。 XXXcopyYYY
算法都不会被认为会更改输入序列(尽管如果您使用别名迭代器,它们可以)。
虽然这真的不能作为 std::remove_copy_if
命名的借口,但我希望它有助于理解一个算法在给定它的名称时做了什么:remove_if
将修改 < em>contents 并产生一个范围,其中与谓词匹配的所有元素都已被删除(返回的范围是由算法的第一个参数到返回的迭代器形成的范围)。 std::remove_copy_if
做同样的事情,但不是修改底层序列,而是创建序列的 拷贝,其中与谓词匹配的元素已被删除。即所有*copy*算法都等价于copy然后应用原算法(注意等价是逻辑的,std::remove_copy_if
只需要一个OutputIterator,这意味着它不可能复制 然后应用std::remove_if
遍历复制的范围。
同样的推理可以应用于其他变异算法:reverse
反转范围内的值(记住,迭代器不访问容器),reverse_copy
将范围内的元素以相反的顺序复制到单独的范围内。
If not, is there an STL algorithm for conditionally removing (moving?) elements from a container & putting them in another container?
STL 中没有这样的算法,但它很容易实现:
template <typename FIterator, typename OIterator, typename Pred>
FIterator splice_if( FIterator first, FIterator last, OIterator out, Pred p )
{
FIterator result = first;
for ( ; first != last; ++first ) {
if ( p( *first ) ) {
*result++ = *first;
} else {
*out++ = *first;
}
}
return result;
}
关于c++ - 为什么 std::remove_copy_if() 不实际删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11928115/
根据http://www.cplusplus.com中的代码 template OutputIterator remove_copy_if (InputIterator first, Input
我正在尝试使用 vector 将 back_insert_iterator 与 remove_copy_if 结合使用,但我遇到了编译错误。 你知道下面的代码为什么不对吗? #include #in
能否请您向我解释一下我在以下代码中做错了什么?我希望第二个 vector 中的值 >= 80 但它是空的。 #include #include #include using namespace
这可能是 STL 中命名最差的函数吗? (反问) std::remove_copy_if() 实际上似乎没有进行任何删除。据我所知,它的行为更像是 copy_if_not。 否定有点令人困惑,但可以使
我试图找到 copy(copy_if) 和 remove_copy(remove_copy_if) STL 算法之间的任何区别,但似乎没有任何实际区别: Source and destination
我已经制定了一个大部分时间都有效的解决方案: #include #include #include #include // Overload that takes a function poi
我试图将 std::ispunct 作为最后一个参数传递给 remove_copy_if,但发现编译失败。但是,如果我传递 ispunct(只是删除了 std::),程序会按预期编译和运行。 代码:
我是一名优秀的程序员,十分优秀!