• <bdo id='eGq3R'></bdo><ul id='eGq3R'></ul>
  • <i id='eGq3R'><tr id='eGq3R'><dt id='eGq3R'><q id='eGq3R'><span id='eGq3R'><b id='eGq3R'><form id='eGq3R'><ins id='eGq3R'></ins><ul id='eGq3R'></ul><sub id='eGq3R'></sub></form><legend id='eGq3R'></legend><bdo id='eGq3R'><pre id='eGq3R'><center id='eGq3R'></center></pre></bdo></b><th id='eGq3R'></th></span></q></dt></tr></i><div id='eGq3R'><tfoot id='eGq3R'></tfoot><dl id='eGq3R'><fieldset id='eGq3R'></fieldset></dl></div>
    <legend id='eGq3R'><style id='eGq3R'><dir id='eGq3R'><q id='eGq3R'></q></dir></style></legend>

      <tfoot id='eGq3R'></tfoot>
      1. <small id='eGq3R'></small><noframes id='eGq3R'>

        为什么不从 std::allocator 继承

        时间:2023-08-02

        <small id='7eK4h'></small><noframes id='7eK4h'>

            <tfoot id='7eK4h'></tfoot>
                  <bdo id='7eK4h'></bdo><ul id='7eK4h'></ul>

                  <i id='7eK4h'><tr id='7eK4h'><dt id='7eK4h'><q id='7eK4h'><span id='7eK4h'><b id='7eK4h'><form id='7eK4h'><ins id='7eK4h'></ins><ul id='7eK4h'></ul><sub id='7eK4h'></sub></form><legend id='7eK4h'></legend><bdo id='7eK4h'><pre id='7eK4h'><center id='7eK4h'></center></pre></bdo></b><th id='7eK4h'></th></span></q></dt></tr></i><div id='7eK4h'><tfoot id='7eK4h'></tfoot><dl id='7eK4h'><fieldset id='7eK4h'></fieldset></dl></div>
                • <legend id='7eK4h'><style id='7eK4h'><dir id='7eK4h'><q id='7eK4h'></q></dir></style></legend>
                    <tbody id='7eK4h'></tbody>

                • 本文介绍了为什么不从 std::allocator 继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

                  我像这样创建了自己的分配器:

                  I created my own allocator like so:

                  template<typename T>
                  class BasicAllocator
                  {
                      public:
                          typedef size_t size_type;
                          typedef ptrdiff_t difference_type;
                          typedef T* pointer;
                          typedef const T* const_pointer;
                          typedef T& reference;
                          typedef const T& const_reference;
                          typedef T value_type;
                  
                  
                          BasicAllocator() throw() {};
                          BasicAllocator (const BasicAllocator& other) throw() {};
                  
                          template<typename U>
                          BasicAllocator (const BasicAllocator<U>& other) throw() {};
                  
                          template<typename U>
                          BasicAllocator& operator = (const BasicAllocator<U>& other) {return *this;}
                          BasicAllocator<T>& operator = (const BasicAllocator& other) {return *this;}
                          ~BasicAllocator() {}
                  
                          pointer address (reference value) const {return &value;}
                          const_pointer address (const_reference value) const {return &value;}
                  
                          pointer allocate (size_type n, const void* hint = 0) {return static_cast<pointer> (::operator new (n * sizeof (value_type) ) );}
                          void deallocate (void* ptr, size_type n) {::operator delete (static_cast<T*> (ptr) );}
                  
                          template<typename U, typename... Args>
                          void construct (U* ptr, Args&&  ... args) {::new (static_cast<void*> (ptr) ) U (std::forward<Args> (args)...);}
                          void construct (pointer ptr, const T& val) {new (static_cast<T*> (ptr) ) T (val);}
                  
                          template<typename U>
                          void destroy (U* ptr) {ptr->~U();}
                          void destroy (pointer ptr) {ptr->~T();}
                  
                          size_type max_size() const {return std::numeric_limits<std::size_t>::max() / sizeof (T);} /**return std::size_t(-1);**/
                  
                          template<typename U>
                          struct rebind
                          {
                              typedef BasicAllocator<U> other;
                          };
                  };
                  

                  但我想知道为什么我永远不应该从 std::allocator 继承.是因为它没有虚拟析构函数吗?我看过很多帖子说应该创建自己的而不是继承.我明白为什么我们不应该继承 std::stringstd::vector 但是继承 std::allocator 有什么问题?

                  But I want to know why I should never inherit from std::allocator. Is it because it doesn't have a virtual destructor? I've seen many posts saying that one should create their own and not inherit. I understand why we shouldn't inherit std::string and std::vector but what is wrong with inheriting std::allocator?

                  我可以继承上面的类吗?或者我需要一个虚拟析构函数来做到这一点?

                  Can I inherit my class above? Or do I need a virtual destructor to do that?

                  为什么?

                  推荐答案

                  很多人会在这个帖子里发帖说你不应该从 std::allocator 继承,因为它没有有一个虚拟析构函数.他们将讨论多态性以及通过指向基类的指针进行切片和删除,这些都不是标准第 17.6.3.5 节 [allocator.requirements] 中详述的分配器要求所允许的.除非有人证明从 std::allocator 派生的类不能满足其中一个要求,否则就是简单的货物崇拜心态.

                  A lot of people are going to post in this thread that you should not inherit from std::allocator because it doesn't have a virtual destructor. They'll talk about polymorphism and slicing and deleting via pointer-to-base class, none of which are permitted by the allocator requirements as detailed in section 17.6.3.5 [allocator.requirements] of the standard. Until someone demonstrates that a class derived from std::allocator fails to meet one of those requirements, it's simple cargo cult mentality.

                  也就是说,在 C++11 中几乎没有理由从 std::allocator 派生.C++11 对分配器的大修引入了特征模板 std::allocator_traits 位于分配器和它的用户之间,并通过模板元编程为许多必需的功能提供合理的默认值.C++11 中的最小分配器可以很简单:

                  That said, there is little reason to derive from std::allocator in C++11. C++11's overhaul of allocators introduced the traits template std::allocator_traits to sit between an allocator and its users and provide reasonable defaults for many of the required features via template metaprogramming. A minimal allocator in C++11 can be as simple as:

                  template <typename T>
                  struct mallocator {
                    using value_type = T;
                  
                    mallocator() = default;
                    template <class U>
                    mallocator(const mallocator<U>&) {}
                  
                    T* allocate(std::size_t n) {
                      std::cout << "allocate(" << n << ") = ";
                      if (n <= std::numeric_limits<std::size_t>::max() / sizeof(T)) {
                        if (auto ptr = std::malloc(n * sizeof(T))) {
                          return static_cast<T*>(ptr);
                        }
                      }
                      throw std::bad_alloc();
                    }
                    void deallocate(T* ptr, std::size_t n) {
                      std::free(ptr);
                    }
                  };
                  
                  template <typename T, typename U>
                  inline bool operator == (const mallocator<T>&, const mallocator<U>&) {
                    return true;
                  }
                  
                  template <typename T, typename U>
                  inline bool operator != (const mallocator<T>& a, const mallocator<U>& b) {
                    return !(a == b);
                  }
                  

                  std::allocator_traits 的正确使用尚未完全出现在所有标准库中.例如,当使用 GCC 4.8.1 编译时,上面的示例分配器不能与 std::list 一起正常工作 - std::list 代码抱怨缺少成员,因为还没更新.

                  Proper use of std::allocator_traits isn't fully present in all standard libraries yet. For example, the sample allocator above doesn't work correctly with std::list when compiled with GCC 4.8.1 - the std::list code complains about missing members since it hasn't been updated yet.

                  这篇关于为什么不从 std::allocator 继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                  上一篇:C++ 对 vtable 和继承的未定义引用 下一篇:C++ 继承和函数覆盖

                  相关文章

                  最新文章

                  • <bdo id='xk0I5'></bdo><ul id='xk0I5'></ul>

                    <tfoot id='xk0I5'></tfoot>
                    <legend id='xk0I5'><style id='xk0I5'><dir id='xk0I5'><q id='xk0I5'></q></dir></style></legend>
                  1. <small id='xk0I5'></small><noframes id='xk0I5'>

                  2. <i id='xk0I5'><tr id='xk0I5'><dt id='xk0I5'><q id='xk0I5'><span id='xk0I5'><b id='xk0I5'><form id='xk0I5'><ins id='xk0I5'></ins><ul id='xk0I5'></ul><sub id='xk0I5'></sub></form><legend id='xk0I5'></legend><bdo id='xk0I5'><pre id='xk0I5'><center id='xk0I5'></center></pre></bdo></b><th id='xk0I5'></th></span></q></dt></tr></i><div id='xk0I5'><tfoot id='xk0I5'></tfoot><dl id='xk0I5'><fieldset id='xk0I5'></fieldset></dl></div>