C++ source code analysis - sequence container adapter (stack, queue, priority_queue)

  Foreword : I have read Mr. Hou's "STL Source Code Analysis" before, but that was many years ago. Now, sometimes you need to understand the implementation of STL used in actual work to check problems and crashes at work. Therefore, it is planned to go through the source code of STL again.
  Abstract : This article describes allocatorthe implementation of libcxx in llvm.
  Keywords : stack, queue, priority_queue
  Others : Reference code LLVM-libcxx
  Note : The implementation of llvm is different from the implementation of gnu and msvc when referring to the code. The article assumes that you are already very familiar with the data structure, and will not delve into the details of the corresponding data structure.

  There are three commonly used containers in C++, which are not containers but adapters, that is, they actually use existing containers to realize the functions of corresponding containers.

  • stackProvides FILO (First In Last Out) capability.
  • queueProvides FIFO capability.
  • priority_queuepriority queue.

1 stack

  stackThe implementation in STL is passed by default deque, and of course the container can also be specified, but the premise is that the corresponding container contains some operation interfaces. It stackcan also be seen from the adapter that another container is wrapped in this class, and then the interface of the container is used to realize the required functions. If you expect to use a custom container, the corresponding container should support pop_back(), push_back(), size(), empty()such interfaces.

template <class _Tp, class _Container /*= deque<_Tp>*/>
class _LIBCPP_TEMPLATE_VIS stack{
    
    
public:
    typedef _Container                               container_type;
    typedef typename container_type::value_type      value_type;
    typedef typename container_type::reference       reference;
    typedef typename container_type::const_reference const_reference;
    typedef typename container_type::size_type       size_type;
    static_assert((is_same<_Tp, value_type>::value), "" );

protected:
    container_type c;
};

  stackThe implementation of is relatively simple, there is nothing to say. It should be noted that it is implemented topseparately popinstead of directly implementing an interface to ensure exception safety. If it is implemented in the same interface, it is normal when the element is obtained, the data is popped, and the abnormal data will be lost when copying the data object during the return process.

void push(const value_type& __v) {
    
    c.push_back(__v);}
const_reference top() const {
    
    return c.back();}
void pop() {
    
    c.pop_back();}

2 queue

  queueThe stacksame as the definition, the default is to wrap adeque

template <class _Tp, class _Container /*= deque<_Tp>*/>
class _LIBCPP_TEMPLATE_VIS queue{
    
    
public:
    typedef _Container                               container_type;
    typedef typename container_type::value_type      value_type;
    typedef typename container_type::reference       reference;
    typedef typename container_type::const_reference const_reference;
    typedef typename container_type::size_type       size_type;
    static_assert((is_same<_Tp, value_type>::value), "" );

protected:
    container_type c;
};

  dequeThe implementation is also very simple, not much description.

    bool      empty() const {
    
    return c.empty();}
    _LIBCPP_INLINE_VISIBILITY
    size_type size() const  {
    
    return c.size();}

    _LIBCPP_INLINE_VISIBILITY
    reference       front()       {
    
    return c.front();}
    _LIBCPP_INLINE_VISIBILITY
    const_reference front() const {
    
    return c.front();}
    _LIBCPP_INLINE_VISIBILITY
    reference       back()        {
    
    return c.back();}
    _LIBCPP_INLINE_VISIBILITY
    const_reference back() const  {
    
    return c.back();}

    _LIBCPP_INLINE_VISIBILITY
    void push(const value_type& __v) {
    
    c.push_back(__v);}

3 priority_queue

  The priority queue is a heap, and the data in the container is ordered to some extent. The implementation of the priority queue is somewhat different from the previous two. The default is that vectorbecause the elements in the container are ordered to some extent, a comparison function needs to be provided.

template <class _Tp, class _Container = vector<_Tp>, class _Compare = less<typename _Container::value_type> >
class _LIBCPP_TEMPLATE_VIS priority_queue{
    
    
public:
    typedef _Container                               container_type;
    typedef _Compare                                 value_compare;
    typedef typename container_type::value_type      value_type;
    typedef typename container_type::reference       reference;
    typedef typename container_type::const_reference const_reference;
    typedef typename container_type::size_type       size_type;
    static_assert((is_same<_Tp, value_type>::value), "" );

protected:
    container_type c;
    value_compare comp;
};

std::make_heapCreate a heap on the current container   is called when the heap is constructed . The specific implementation is not detailed now, and I will describe it in detail when I look at the algorithm implementation (it is estimated to be a general heap construction algorithm).

template <class _Tp, class _Container, class _Compare>
inline priority_queue<_Tp, _Container, _Compare>::priority_queue(const value_compare& __comp, container_type&& __c)
    : c(_VSTD::move(__c)),
      comp(__comp){
    
    
    _VSTD::make_heap(c.begin(), c.end(), comp);
}

  Both inserting and popping elements also call stdthe implementation of the algorithm.

template <class _Tp, class _Container, class _Compare>
inline void priority_queue<_Tp, _Container, _Compare>::push(value_type&& __v){
    
    
    c.push_back(_VSTD::move(__v));
    _VSTD::push_heap(c.begin(), c.end(), comp);
}

template <class _Tp, class _Container, class _Compare>
inline void priority_queue<_Tp, _Container, _Compare>::pop(){
    
    
    _VSTD::pop_heap(c.begin(), c.end(), comp);
    c.pop_back();
}

Supongo que te gusta

Origin blog.csdn.net/GrayOnDream/article/details/129918753
Recomendado
Clasificación