我是靠谱客的博主 无限信封,最近开发中收集的这篇文章主要介绍GNU C++ 智能指针7-- 解析__allocator_base类1一、关键点解析二、源码分析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

一、关键点解析

1、__cplusplus

2、c++allocator.h文件内容分析

3、_GLIBCXX_VISIBILITY

4、_GLIBCXX_BEGIN_NAMESPACE_VERSION

二、源码分析


一、关键点解析

1、__cplusplus

这是一个c++预定义宏

c++ 98中,是199711L
c++ 11中,是201103L

2、c++allocator.h文件内容分析

#if __cplusplus >= 201103L
namespace std
{
  /**
   *  @brief  An alias to the base class for std::allocator.
   *  @ingroup allocators
   *
   *  Used to set the std::allocator base class to
   *  __gnu_cxx::new_allocator.
   *
   *  @tparam  _Tp  Type of allocated object.
    */
  template<typename _Tp>
    using __allocator_base = __gnu_cxx::new_allocator<_Tp>;
}
#else
// Define new_allocator as the base class to std::allocator.
# define __allocator_base  __gnu_cxx::new_allocator
#endif

#endif

从上述代码可以发现__allocator_base为__gnu_cxx::new_allocator<_Tp>

3、_GLIBCXX_VISIBILITY

It's a preprocessor macro. And is defined as:

// If platform uses neither visibility nor psuedo-visibility,
// specify empty default for namespace annotation macros.
#ifndef _GLIBCXX_PSEUDO_VISIBILITY
# define _GLIBCXX_PSEUDO_VISIBILITY(V)
#endif
#if _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY
#define _GLIBCXX_VISIBILITY(V) __attribute__ ((__visibility__ (#V)))
#else
#define _GLIBCXX_VISIBILITY(V) 
#endif

So if _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY is true then in your case it will expand to:

__attribute__ (( __visibility__ ("default")))

else if _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY is false it will do nothing.

The __visibility__ attribute is used for defining the visibility of the symbols in a DSO file. Using "hidden" instead of "default" can be used to hide symbols from things outside the DSO.

For example:

__attribute__ ((__visibility__("default"))) void foo();
__attribute__ ((__visibility__("hidden"))) void bar();

The function foo() would be useable from outside the DSO whereas bar() is basically private and can only be used inside the DSO.

You can read a bit more about the __visibility__ attribute here: Visibility - GCC Wiki

4、_GLIBCXX_BEGIN_NAMESPACE_VERSION

// Defined if inline namespaces are used for versioning.
# define _GLIBCXX_INLINE_VERSION 0 

// Inline namespace for symbol versioning.
#if _GLIBCXX_INLINE_VERSION

namespace std
{
  inline namespace __7 { }

  namespace rel_ops { inline namespace __7 { } }

  namespace tr1
  {
    inline namespace __7 { }
    namespace placeholders { inline namespace __7 { } }
    namespace regex_constants { inline namespace __7 { } }
    namespace __detail { inline namespace __7 { } }
  }

  namespace tr2
  { inline namespace __7 { } }

  namespace decimal { inline namespace __7 { } }

  namespace chrono { inline namespace __7 { } }
  namespace placeholders { inline namespace __7 { } }
  namespace regex_constants { inline namespace __7 { } }
  namespace this_thread { inline namespace __7 { } }

  namespace experimental { inline namespace __7 { } }

  namespace __detail { inline namespace __7 { } }
}

namespace __gnu_cxx
{
  inline namespace __7 { }
  namespace __detail { inline namespace __7 { } }
}
# define _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __7 {
# define _GLIBCXX_END_NAMESPACE_VERSION }
#else
# define _GLIBCXX_BEGIN_NAMESPACE_VERSION
# define _GLIBCXX_END_NAMESPACE_VERSION
#endif

inlinespace是c++11的新特性,示例代码如下:

#include <iostream>
using namespace std;


namespace all
{
    //inline作用为默认调用
    inline namespace V2022
    {
        void fun(int num)
        {
            cout << "int" << "V2017" << endl;
        }
    }
    namespace V2021
    {
        void fun(int num)
        {
            cout << "int" << "V2021" << endl;
        }

        void fun(double num)
        {
            cout << "double" << "V2021" << endl;
        }
    }
}

void main()
{
    all::fun(1);
    all::V2021::fun(1);
    cin.get();
}

二、源码分析

namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  using std::size_t;
  using std::ptrdiff_t;

  /**
   *  @brief  An allocator that uses global new, as per [20.4].
   *  @ingroup allocators
   *
   *  This is precisely the allocator defined in the C++ Standard. 
   *    - all allocation calls operator new
   *    - all deallocation calls operator delete
   *
   *  @tparam  _Tp  Type of allocated object.
   */
  template<typename _Tp>
    class new_allocator
    {
    public:
      typedef size_t     size_type;
      typedef ptrdiff_t  difference_type;
      typedef _Tp*       pointer;
      typedef const _Tp* const_pointer;
      typedef _Tp&       reference;
      typedef const _Tp& const_reference;
      typedef _Tp        value_type;

      template<typename _Tp1>
        struct rebind
        { typedef new_allocator<_Tp1> other; };

#if __cplusplus >= 201103L
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 2103. propagate_on_container_move_assignment
      typedef std::true_type propagate_on_container_move_assignment;
#endif

      new_allocator() _GLIBCXX_USE_NOEXCEPT { }

      new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { }

      template<typename _Tp1>
        new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { }

      ~new_allocator() _GLIBCXX_USE_NOEXCEPT { }

      pointer
      address(reference __x) const _GLIBCXX_NOEXCEPT
      { return std::__addressof(__x); }

      const_pointer
      address(const_reference __x) const _GLIBCXX_NOEXCEPT
      { return std::__addressof(__x); }

      // NB: __n is permitted to be 0.  The C++ standard says nothing
      // about what the return value is when __n == 0.
      pointer
      allocate(size_type __n, const void* = 0)
      { 
	if (__n > this->max_size())
	  std::__throw_bad_alloc();

	return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
      }

      // __p is not permitted to be a null pointer.
      void
      deallocate(pointer __p, size_type)
      { ::operator delete(__p); }

      size_type
      max_size() const _GLIBCXX_USE_NOEXCEPT
      { return size_t(-1) / sizeof(_Tp); }

#if __cplusplus >= 201103L
      template<typename _Up, typename... _Args>
        void
        construct(_Up* __p, _Args&&... __args)
	{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

      template<typename _Up>
        void 
        destroy(_Up* __p) { __p->~_Up(); }
#else
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 402. wrong new expression in [some_] allocator::construct
      void 
      construct(pointer __p, const _Tp& __val) 
      { ::new((void *)__p) _Tp(__val); }

      void 
      destroy(pointer __p) { __p->~_Tp(); }
#endif
    };

  template<typename _Tp>
    inline bool
    operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
    { return true; }
  
  template<typename _Tp>
    inline bool
    operator!=(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
    { return false; }

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

最后

以上就是无限信封为你收集整理的GNU C++ 智能指针7-- 解析__allocator_base类1一、关键点解析二、源码分析的全部内容,希望文章能够帮你解决GNU C++ 智能指针7-- 解析__allocator_base类1一、关键点解析二、源码分析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部