std::remove并非你所想

结论

  1. std::remove并没有删除元素,只是将指定元素交换到了容器后面
  2. remove后,容器中元素内容可能发生变化(不存在指定元素则无变化)
  3. 删除元素需要配合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

实现过程

  1. 代码
	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;
    }
  1. 解析
    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得到可以删除的迭代器,该迭代器后面所有元素可以删除
posted @ 2022-09-28 20:01  flxx  阅读(73)  评论(0编辑  收藏  举报