Is Stephen Lavavej's Mallocator the same in C++11?

前端 未结 2 1680
抹茶落季
抹茶落季 2021-02-07 23:41

8 years ago, Stephen Lavavej published this blog post containing a simple allocator implementation, named the \"Mallocator\". Since then we\'ve transitioned to the era of C++11

相关标签:
2条回答
  • 2021-02-08 00:01

    STL himself has an answer to this question in his STL Features and Implementation techniques talk at CppCon 2014 (Starting at 26'30).

    The slides are on github.

    I merged the content of slides 28 and 29 below:

    #include <stdlib.h> // size_t, malloc, free
    #include <new> // bad_alloc, bad_array_new_length
    template <class T> struct Mallocator {
      typedef T value_type;
      Mallocator() noexcept { } // default ctor not required
      template <class U> Mallocator(const Mallocator<U>&) noexcept { }
      template <class U> bool operator==(
        const Mallocator<U>&) const noexcept { return true; }
      template <class U> bool operator!=(
        const Mallocator<U>&) const noexcept { return false; }
    
      T * allocate(const size_t n) const {
          if (n == 0) { return nullptr; }
          if (n > static_cast<size_t>(-1) / sizeof(T)) {
              throw std::bad_array_new_length();
          }
          void * const pv = malloc(n * sizeof(T));
          if (!pv) { throw std::bad_alloc(); }
          return static_cast<T *>(pv);
      }
      void deallocate(T * const p, size_t) const noexcept {
          free(p);
      }
    };
    

    Note that it handles correctly the possible overflow in allocate.

    0 讨论(0)
  • 2021-02-08 00:19

    As @kerrek suggested, here is a Mallocator that is based off the linked arena allocator with the arena part deleted.

    template<class T>
    struct Mallocator11 {
      using value_type = T;
      using pointer = T*;
      using propagate_on_container_copy_assignment = std::true_type;
      using propagate_on_container_move_assignment = std::true_type;
      using propagate_on_container_swap = std::true_type;
    
      Mallocator11(Mallocator11 const&) = default;
      Mallocator11& operator=(Mallocator11 const&) = default;
      Mallocator11()=default;
      template<class U>
      Mallocator11(Mallocator11<U> const&) noexcept {}
      template<class U>
      Mallocator11& operator=(Mallocator11<U> const&) noexcept {return *this}
    
    
      pointer allocate(std::size_t n) {
        if (std::size_t(-1) / sizeof(T) < n)
          throw std::bad_array_new_length(); // or something else
        if (!n) return nullptr; // zero means null, not throw
        if(auto*r= static_cast<pointer>(malloc(n * sizeof(T))))
          return r;
        throw std::bad_alloc();
      }
      void deallocate(pointer p, std::size_t n) {
        free(p);
      }
      template<class U>
      bool operator==(Mallocator11<U> const& rhs) const {
        return true;
      }
      template<class U>
      bool operator!=(Mallocator11<U> const& rhs) const {
        return false;
      }
    };
    

    Lots less code. Some traits for propogation.

    0 讨论(0)
提交回复
热议问题