// 序列容器 --- 需要更新 迭代器 for (auto it = v.begin(); it != v.end();) { if (pred(*it)) { // 此时已经更新了 迭代器, 因此不需要 ++ it = v.erase(it); } else { // 对于不满足条件的值, 直接 ++ it++; } }
// set 使用 for 循环 --- 需要及时更新 迭代器 for (auto it = s.begin(); it != s.end(); ) { // 对于所有非法的值, 删除之后再移动迭代器到下一个位置 if (pred(*it)) s.erase(it++); // 合法的值, 直接移动即可 else it++; }
template <class_Ty> classallocator { public: static_assert(!is_const_v<_Ty>, "The C++ Standard forbids containers of const elements " "because allocator<const T> is ill-formed.");
using _From_primary = allocator;
using value_type = _Ty;
#if _HAS_DEPRECATED_ALLOCATOR_MEMBERS using pointer _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS = _Ty*; using const_pointer _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS = const _Ty*;
using reference _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS = _Ty&; using const_reference _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS = const _Ty&; #endif// _HAS_DEPRECATED_ALLOCATOR_MEMBERS
using size_type = size_t; using difference_type = ptrdiff_t;
using propagate_on_container_move_assignment = true_type; using is_always_equal _CXX20_DEPRECATE_IS_ALWAYS_EQUAL = true_type;
#if _HAS_DEPRECATED_ALLOCATOR_MEMBERS // rebind 的实现 template <class_Other> struct_CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS rebind { using other = allocator<_Other>; };
_CONSTEXPR20 voiddeallocate(_Ty* const _Ptr, constsize_t _Count){ _STL_ASSERT(_Ptr != nullptr || _Count == 0, "null pointer cannot point to a block of non-zero size"); // no overflow check on the following multiply; we assume _Allocate did that check _Deallocate<_New_alignof<_Ty>>(_Ptr, sizeof(_Ty) * _Count); }
_NODISCARD_RAW_PTR_ALLOC _CONSTEXPR20 __declspec(allocator) _Ty* allocate(_CRT_GUARDOVERFLOW constsize_t _Count){ static_assert(sizeof(value_type) > 0, "value_type must be complete before calling allocate."); returnstatic_cast<_Ty*>(_Allocate<_New_alignof<_Ty>>(_Get_size_of_n<sizeof(_Ty)>(_Count))); }
template <typename T> structMyAllocator { using pointer = T*; using const_pointer = const T*; using reference = T&; using const_reference = const T&; using value_type = T; using size_type = size_t; using difference_type = std::ptrdiff_t;
pointer allocate(size_t numObjects, constvoid *localityHint = 0){ auto ptr = makeShared(numObjects * sizeof(T)); // print message and allocate memory with global new std::cerr << "allocate " << numObjects << " element(s)" << " of size " << sizeof(T) << " at " << ptr << std::endl; returnstatic_cast<pointer>(ptr); }
// initialize elements of allocated storage p with value value voidconstruct(pointer p, const T& value){ // initialize memory with placement new new((void*)p)T(value); }
// destroy elements of initialized storage p voiddestroy(pointer p){ // destroy objects by calling their destructor p->~T(); }
voiddeallocate(pointer dataPtr, size_t numObjects){ // print message and deallocate memory with global delete std::cerr << "deallocate " << numObjects << " element(s)" << " of size " << sizeof(T) << " at: " << (void*)dataPtr << std::endl; freeShared(dataPtr); }
template <typename U> structrebind { using other = MyAllocator<U>; };
/* constructors and destructor * - nothing to do because the allocator has no state */ MyAllocator() throw() { } MyAllocator(const MyAllocator&) throw() { } template <class U> MyAllocator (const MyAllocator<U>&) throw() { } ~MyAllocator() throw() { }
// return maximum number of elements that can be allocated size_type max_size () constthrow() { return std::numeric_limits<std::size_t>::max() / sizeof(T); }
};
// return that all specializations of this allocator are interchangeable template <classT1, classT2> booloperator== (const MyAllocator<T1>&, const MyAllocator<T2>&) throw() { returntrue; }