std::remove并非你所想
结论
- std::remove并没有删除元素,只是将指定元素交换到了容器后面
- remove后,容器中元素内容可能发生变化(不存在指定元素则无变化)
- 删除元素需要配合erase完成
std::vector<int> ids{ 1, 3, 5, 3, 7 }; // 1 3 5 3 7
auto tar = std::remove(ids.begin(), ids.end(), 3); // 1 5 7 3 7
ids.erase(tar, ids.end()); // 1 5 7
实现过程
- 代码
template <class _FwdIt, class _Pr>
_NODISCARD _CONSTEXPR20 _FwdIt remove_if(_FwdIt _First, const _FwdIt _Last, _Pr _Pred) {
// remove each satisfying _Pred
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
_UFirst = _STD find_if(_UFirst, _ULast, _Pass_fn(_Pred));
auto _UNext = _UFirst;
if (_UFirst != _ULast) {
while (++_UFirst != _ULast) {
if (!_Pred(*_UFirst)) {
*_UNext = _STD move(*_UFirst);
++_UNext;
}
}
}
_Seek_wrapped(_First, _UNext);
return _First;
}
// _Get_unwrapped提取迭代器包含元素的指针
template <class _Iter>
_NODISCARD constexpr decltype(auto) _Get_unwrapped(_Iter&& _It) {
// unwrap an iterator previously subjected to _Adl_verify_range or otherwise validated
if constexpr (is_pointer_v<decay_t<_Iter>>) { // special-case pointers and arrays
return _It + 0;
} else if constexpr (_Unwrappable_v<_Iter>) {
return static_cast<_Iter&&>(_It)._Unwrapped();
} else {
return static_cast<_Iter&&>(_It);
}
}
_NODISCARD _CONSTEXPR20_CONTAINER const value_type* _Unwrapped() const noexcept {
return _Unfancy(_Ptr);
}
template <class _Ptrty>
_NODISCARD constexpr auto _Unfancy(_Ptrty _Ptr) noexcept { // converts from a fancy pointer to a plain pointer
return _STD addressof(*_Ptr);
}
template <class _Ty>
_NODISCARD constexpr _Ty* addressof(_Ty& _Val) noexcept {
return __builtin_addressof(_Val);
}
// 获取容器中指定元素的第一个迭代器
template <class _InIt, class _Ty>
_NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(const _InIt _First, const _InIt _Last, const _Ty& _Val) {
// find first matching _Val; choose optimization
// activate optimization for contiguous iterators to (const) bytes and integral values
return _Find_unchecked1(_First, _Last, _Val, bool_constant<_Memchr_in_find_is_safe<_InIt, _Ty>>{});
}
template <class _InIt, class _Ty>
_NODISCARD constexpr _InIt _Find_unchecked1(_InIt _First, const _InIt _Last, const _Ty& _Val, false_type) {
// find first matching _Val
for (; _First != _Last; ++_First) {
if (*_First == _Val) {
break;
}
}
return _First;
}
- 解析
step1: 1 3 5 3 7 // 原始数据
step2: 获取指定元素第一个迭代器_UFirst = 1 _UNext = 1
step3: 1 5 5 3 7 // 5 != 3 将5向前拷贝到3
step4: 1 5 5 3 7 // 3 == 3 保持不动
step5: 1 5 7 3 7 // 7 != 3 将7向前拷贝到5
step6: swap _First _UNext得到可以删除的迭代器,该迭代器后面所有元素可以删除
本文来自博客园,作者:flxx,转载请注明原文链接:https://www.cnblogs.com/faithlocus/p/16739382.html