C++ STL 容器设计与实现分析 -- array

1、array(C++11)

array 是固定长度的数组,定义时就指定长度,一旦定义长度不能更改(不能扩容)。

  template<typename _Tp, std::size_t _Nm>
    struct array
    {
      typedef _Tp                           value_type;
      typedef value_type*                  pointer;
      typedef const value_type*                       const_pointer;
      typedef value_type&                             reference;
      typedef const value_type&                       const_reference;
      typedef value_type*                        iterator;
      typedef const value_type*                  const_iterator;
      typedef std::size_t                              size_type;
      typedef std::ptrdiff_t                             difference_type;
      typedef std::reverse_iterator<iterator>          reverse_iterator;
      typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;

      // Support for zero-sized arrays mandatory.
      typedef __array_traits<_Tp, _Nm> _AT_Type;
      typename _AT_Type::_Type                         _M_elems;
      /***/
  • array 有两个模板参数:元素类型和元素个数,元素个数可以是 0
  • pointer/reference/iterator 直接是元素类型相应类型

__array_traits 使用了模板偏特化支持 array 元素个数可以为 0。当元素个数为 0 时,定义了一个空类 _Type。_S_ref() 和 _S_ptr() 使用 nullptr 构造返回值。

  template<typename _Tp, std::size_t _Nm>
    struct __array_traits
    {
      typedef _Tp _Type[_Nm];
      typedef __is_swappable<_Tp> _Is_swappable;
      typedef __is_nothrow_swappable<_Tp> _Is_nothrow_swappable;

      static constexpr _Tp&
      _S_ref(const _Type& __t, std::size_t __n) noexcept
      { return const_cast<_Tp&>(__t[__n]); }

      static constexpr _Tp*
      _S_ptr(const _Type& __t) noexcept
      { return const_cast<_Tp*>(__t); }
    };

 template<typename _Tp>
   struct __array_traits<_Tp, 0>
   {
     struct _Type { };
     typedef true_type _Is_swappable;
     typedef true_type _Is_nothrow_swappable;

     static constexpr _Tp&
     _S_ref(const _Type&, std::size_t) noexcept
     { return *static_cast<_Tp*>(nullptr); }

     static constexpr _Tp*
     _S_ptr(const _Type&) noexcept
     { return nullptr; }
   };

1.1、data()

如果 array 元素个数为 0,data() 返回 nullptr,否则返回数组首地址。

      [[__gnu__::__const__, __nodiscard__]]
      _GLIBCXX17_CONSTEXPR pointer
      data() noexcept
      { return _AT_Type::_S_ptr(_M_elems); }

1.2、begin()/end()/front()/back()

begin() 和 end() 返回 iterator,从定义可知,迭代器就是原始指针。

      [[__gnu__::__const__, __nodiscard__]]
      _GLIBCXX17_CONSTEXPR iterator
      begin() noexcept
      { return iterator(data()); }

      [[__gnu__::__const__, __nodiscard__]]
      _GLIBCXX17_CONSTEXPR iterator
      end() noexcept
      { return iterator(data() + _Nm); }

front() 和 back() 返回的是 reference。非 const 和 const 类型实现不同,非 const 类型借助 begin() 和 end() 实现,而 const 类型使用 _S_ref() 实现。

      [[__nodiscard__]]
      _GLIBCXX17_CONSTEXPR reference
      front() noexcept
      {
    __glibcxx_requires_nonempty();
    return *begin();
      }

      [[__nodiscard__]]
      constexpr const_reference
      front() const noexcept
      {
#if __cplusplus >= 201402L
    __glibcxx_requires_nonempty();
#endif
    return _AT_Type::_S_ref(_M_elems, 0);
      }

      [[__nodiscard__]]
      _GLIBCXX17_CONSTEXPR reference
      back() noexcept
      {
    __glibcxx_requires_nonempty();
    return _Nm ? *(end() - 1) : *end();
      }

      [[__nodiscard__]]
      constexpr const_reference
      back() const noexcept
      {
#if __cplusplus >= 201402L
    __glibcxx_requires_nonempty();
#endif
    return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
                : _AT_Type::_S_ref(_M_elems, 0);
      }

1.3、operator[]/at

      // Element access.
      [[__nodiscard__]]
      _GLIBCXX17_CONSTEXPR reference
      operator[](size_type __n) noexcept
      {
    __glibcxx_requires_subscript(__n);
    return _AT_Type::_S_ref(_M_elems, __n);
      }

      _GLIBCXX17_CONSTEXPR reference
      at(size_type __n)
      {
    if (__n >= _Nm)
      std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
                        ">= _Nm (which is %zu)"),
                    __n, _Nm);
    return _AT_Type::_S_ref(_M_elems, __n);
      }
欢迎关注公众号“源知源为”,阅读更多技术干货
#C++##STL##容器#
C/C++基础 文章被收录于专栏

C/C++ 语言基础

全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务