我的矢量有什么问题<T>::擦除这里?
What's wrong with my vector<T>::erase here?
我的程序中有两个vector<T>
,分别称为active
和non_active
。这指的是它所包含的对象,以及它们是否在使用中。
我有一些代码可以循环active
向量,并检查任何可能处于非活动状态的对象。我将这些添加到循环中的temp_list
中。
然后在循环之后,我取我的temp_list
,对temp_list
中的所有元素进行non_active.insert
。
之后,我在active
向量上调用erase
,并将其传递给temp_list
进行擦除。
然而,由于某种原因,erase
崩溃了。
这是代码:
non_active.insert(non_active.begin(), temp_list.begin(), temp_list.end());
active.erase(temp_list.begin(), temp_list.end());
我得到这样的断言:
Expression:("_Pvector == NULL || (((_Myvec*)_Pvector)->_Myfirst <= _Ptr && _Ptr <= ((_Myvect*)_Pvector)->_Mylast)",0)
我在网上看到了一个擦除-删除习惯用法,但不确定如何将其应用于从vector<T>
中删除一系列元素
我没有使用C++11。
erase
期望传递给它的迭代器范围位于当前向量内。不能将从其他向量获得的迭代器传递给erase
。
这里有一个可能的,但效率低下的,由lambdas支持的C++11解决方案:
active.erase(std::remove_if(active.begin(), active.end(), [](const T& x)
{
return std::find(temp_list.begin(), temp_list.end(), x) != temp_list.end();
}), active.end());
这是一个没有λ的等价的C++03解:
template<typename Container>
class element_of
{
Container& container;
element_of(Container& container) : container(container) {}
public:
template<typename T>
bool operator()(const T& x) const
{
return std::find(container.begin(), container.end(), x)
!= container.end();
}
};
// ...
active.erase(std::remove_if(active.begin(), active.end(),
element_of<std::vector<T> >(temp_list)),
active.end());
如果将temp_list
替换为std::set
,将std::find_if
替换为集合上的find
成员函数调用,则性能应该可以接受。
擦除方法旨在接受同一容器对象的迭代器。您正试图将迭代器传递到temp_list以用于从活动中擦除元素,这是有充分理由不允许的,因为Sequence的范围擦除方法旨在指定要删除的Sequence中的范围。迭代器在这个序列中很重要,因为否则我们将指定一个要擦除的值范围,而不是同一容器中的一个范围,这是一个成本高得多的操作。
你试图执行的逻辑类型向我表明,一个集合或列表可能更适合这个目的。也就是说,您正试图从容器中间擦除与特定条件匹配的各种元素,并将它们转移到另一个容器,这样就可以消除对temp_list的需求。
例如,对于列表,它可以像下面这样简单:
for (ActiveList::iterator it = active.begin(); it != active.end();)
{
if (it->no_longer_active())
{
inactive.push_back(*it);
it = active.erase(it);
}
else
++it;
}
然而,有时vector可以胜过这些解决方案,并且可能由于其他原因(如确保连续内存)而需要vector。在这种情况下,std::remove_if是您的最佳选择。
示例:
bool not_active(const YourObjectType& obj);
active_list.erase(
remove_if(active_list.begin(), active_list.end(), not_active),
active_list.end());
有关这方面的更多信息可以在主题"删除习语"下找到,您可能需要谓词函数对象,这取决于确定对象是否不再活动所需的外部状态。
您实际上可以使擦除/删除习惯用法适用于您的情况。您只需要将值移动到另一个容器,然后std::remove_if
可能会在谓词中对其进行混洗。
template<class OutIt, class Pred>
struct copy_if_predicate{
copy_if_predicate(OutIt dest, Pred p)
: dest(dest), pred(p) {}
template<class T>
bool operator()(T const& v){
if(pred(v)){
*dest++ = v;
return true;
}
return false;
}
OutIt dest;
Pred pred;
};
template<class OutIt, class Pred>
copy_if_predicate<OutIt,Pred> copy_if_pred(OutIt dest, Pred pred){
return copy_if_predicate<OutIt,Pred>(dest,pred);
}
Ideone上的实例。(我直接使用了bool
s来缩短代码,而不必考虑输出等。)
函数std::vector::erase
要求迭代器是这个向量中的迭代器,但您正在从temp_list
传递迭代器。不能从完全不同的容器中删除元素。
active.erase(temp_list.begin(), temp_list.end());
您试图从一个列表中删除元素,但对第二个列表使用迭代器。第一个列表迭代器与第二个列表不同。
我想建议这是应该使用std::list
的一个例子。可以将成员从一个列表拼接到另一个列表。请查看std::list::splice()。
你需要随机访问吗?如果没有,那么您就不需要std::vector
。
请注意,对于list,当您进行拼接时,迭代器和对列表中对象的引用仍然有效。
如果您不介意让实现"具有侵入性",那么您的对象可以包含自己的迭代器值,这样它们就知道自己在哪里。然后,当他们改变状态时,他们可以自动从一个列表"移动"到另一个列表,而不需要为他们遍历整个列表。(如果您希望稍后进行此扫描,您可以让他们自己"注册"以便稍后移动)。
我现在将在这里编写一个算法来运行一个集合,如果条件存在,它将产生std::remove_if,但同时将元素复制到您的"inserter"中。
//fwd iterator must be writable
template< typename FwdIterator, typename InputIterator, typename Pred >
FwdIterator copy_and_remove_if( FwdIterator inp, FwdIterator end, InputIterator outp, Pred pred )
{
for( FwdIterator test = inp; test != end; ++test )
{
if( pred(*test) ) // insert
{
*outp = *test;
++outp;
}
else // keep
{
if( test != inp )
{
*inp = *test;
}
++inp;
}
}
return inp;
}
这有点像std::remove_if
,但会将要删除的内容复制到另一个集合中。您可以这样调用它(对于向量),其中isInactive是一个有效的谓词,指示它应该被移动。
active.erase( copy_and_remove_if( active.begin(), active.end(), std::back_inserter(inactive), isInactive ), active.end() );
传递给erase()
的迭代器应该指向vector
本身;断言是在告诉你他们没有。此版本的erase()
用于擦除vector
之外的范围。
您需要自己对temp_list
进行迭代,并在每一步对迭代器的解引用结果调用active.erase()
。
- 引用一个已擦除类型(void*)的指针
- 擦除while循环中迭代的元素
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- C++擦除(如果存在)
- 在映射擦除c++期间执行循环的次数
- 为什么擦除方法会影响结束方法
- C++ 字符串类擦除成员函数的时空复杂性
- 类型擦除的std::function与虚拟函数调用的开销
- C++14 中unordered_map矢量和擦除删除成语的奇怪行为
- C++ 擦除函数中需要澄清
- 循环挂起迭代的 std::擦除 on std::list
- 擦除许多矢量元素,同时使用'auto'
- 如何擦除冗余输入?
- C++ STL 设置按值擦除
- 如何在C++中允许成员函数的自定义返回类型进行类型擦除?
- 为什么我的向量::擦除调用会抛出"vector subscript out of range"?
- 如何在写入文件时擦除最后一个逗号
- C++:std::ofstream 方法 open() 在第二次迭代时擦除打开的 ifstream 文件
- 双链表的擦除值函数,未知错误
- 如何编写用于多映射插入和擦除功能的 API?