这可能是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;
}
Run Code Online (Sandbox Code Playgroud)
它输出:
-2 0 -1 0 1 2
0 0 1 2
-2 0 -1 0 1 2
Run Code Online (Sandbox Code Playgroud)
我期待如下所见:
-2 0 -1 0 1 2
0 0 1 2
0 0 1 2 ? ? ?
Run Code Online (Sandbox Code Playgroud)
哪里?可以是任何价值.但我很惊讶地发现输入范围是未触及的,并且返回值不能与(在这种情况下)std :: vector :: erase()一起使用.(返回值是输出迭代器.)
Dav*_*eas 20
这可能是STL中最糟糕的命名功能吗?
一些背景信息:在标准库(或原始STL)中,有三个概念,容器,到这些容器的迭代器和应用于迭代器的算法.迭代器充当范围元素的游标和访问者,但没有对容器的引用(如前所述,甚至可能没有底层容器).
这种分离有一个很好的功能,你可以将算法应用于不属于容器的元素范围(考虑像std::istream_iteratoror的迭代器适配器std::ostream_iterator)或属于容器的不考虑所有元素(std::sort( v.begin(), v.begin()+v.size()/2 )缩短容器的前半部分) ).
负面的一面是,因为算法(和迭代器)并不真正知道容器,它们无法真正修改它,它们只能修改存储的元素(这是他们可以访问的).变异算法,像std::remove或std::remove_if在这个前提下工作:它们覆盖与条件不匹配的元素,有效地将它们从容器中删除,但它们不会修改容器,只修改包含的值,这是第二步中的调用者在的擦除,删除成语:
v.erase( std::remove_if( v.begin(), v.end(), pred ),
v.end() );
Run Code Online (Sandbox Code Playgroud)
此外,对于变异算法(执行变更的算法),例如std::remove通过添加copy名称来命名的非变异版本:std::remove_copy_if.没有任何XXXcopyYYY算法被认为是改变输入序列(尽管它们可以使用别名迭代器).
虽然这不是命名的借口,但std::remove_copy_if我希望它有助于理解算法给出其名称的作用:remove_if将修改范围的内容并产生一个范围,其中所有与谓词匹配的元素都已被删除(返回的范围)是由算法的第一个参数形成的返回迭代器).std::remove_copy_if做同样的事情,但它不是修改基础序列,而是创建一个序列的副本,其中已删除与谓词匹配的那些元素.也就是说,所有*copy*算法等同于复制然后应用原始算法(请注意,等价是逻辑的,std::remove_copy_if只需要一个OutputIterator,这意味着它不可能复制,然后应用复制的范围std::remove_if.
同样的推理可以应用于其他变异算法:在范围内reverse反转值(记住,迭代器不访问容器),将范围中reverse_copy的元素以相反的顺序复制到单独的范围.
如果没有,是否有一个STL算法用于有条件地从容器中移除(移动?)元素并将它们放入另一个容器中?
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;
}
Run Code Online (Sandbox Code Playgroud)
是否有一种 STL 算法可以有条件地从容器中删除(移动?)元素并将它们放入另一个容器中?
我能想到的最接近的是std::stable_partition:
std::vector<int> v;
// ...
auto it = std::stable_partition(v.begin(), v.end(), pick_the_good_elements);
std::vector<int> w(std::make_move_iter(it), std::make_move_iter(v.end()));
v.erase(it, v.end());
Run Code Online (Sandbox Code Playgroud)
现在v将包含“好”元素,并将w包含“坏”元素。