Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是斯蒂芬·拉瓦维';s Mallocator与C+中的相同+;11?_C++_C++11_Containers_C++ Standard Library_Allocator - Fatal编程技术网

C++ 是斯蒂芬·拉瓦维';s Mallocator与C+中的相同+;11?

C++ 是斯蒂芬·拉瓦维';s Mallocator与C+中的相同+;11?,c++,c++11,containers,c++-standard-library,allocator,C++,C++11,Containers,C++ Standard Library,Allocator,8年前,Stephen Lavavej发表了一篇包含一个简单分配器实现的文章,名为“Mallocator”。从那时起,我们已经过渡到C++11(很快就是C++17)时代。。。新的语言功能和规则是否影响了Mallocator,或者它仍然是相关的?正如@kerrek所建议的,这里是一个基于arena分配器的Mallocator,删除了arena部分 template<class T> struct Mallocator11 { using value_type = T; usin

8年前,Stephen Lavavej发表了一篇包含一个简单分配器实现的文章,名为“Mallocator”。从那时起,我们已经过渡到C++11(很快就是C++17)时代。。。新的语言功能和规则是否影响了Mallocator,或者它仍然是相关的?

正如@kerrek所建议的,这里是一个基于arena分配器的Mallocator,删除了arena部分

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;
  }
};
模板
结构Mallocator11{
使用值_type=T;
使用指针=T*;
在容器上使用propagate\u\u copy\u assignment=std::true\u type;
在容器上使用propagate\u\u move\u assignment=std::true\u type;
在容器上使用propagate\u\u swap=std::true\u type;
Mallocator11(Mallocator11常量&)=默认值;
Mallocator11&运算符=(Mallocator11常量&)=默认值;
Mallocator11()=默认值;
模板
Mallocator11(Mallocator11常量&)noexcept{}
模板
Mallocator11&运算符=(Mallocator11常量&)noexcept{return*this}
指针分配(标准::大小\u t n){
如果(标准:尺寸t(-1)/sizeof(t)

更少的代码。传播的一些特点。

STL本人在2014年CppCon的演讲中(从26'30开始)回答了这个问题

这些都在github上

我将幻灯片28和29的内容合并到下面:

#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);
  }
};
#包括//size\u t、malloc、免费
#包括//bad\u alloc、bad\u数组\u新长度
模板结构Mallocator{
类型定义T值_类型;
Mallocator()noexcept{}//默认构造函数不是必需的
模板Mallocator(const Mallocator&)noexcept{}
模板布尔算子==(
常量Mallocator&)常量noexcept{return true;}
模板布尔运算符=(
常量Mallocator&)常量noexcept{return false;}
分配(常数大小)常数{
如果(n==0){return nullptr;}
如果(n>静态_-cast(-1)/sizeof(T)){
抛出std::坏数组\新长度();
}
void*const pv=malloc(n*sizeof(T));
如果(!pv){throw std::bad_alloc();}
返回静态_-cast(pv);
}
无效解除分配(T*常数p,大小_T)常数无例外{
自由基(p);
}
};

请注意,它正确处理分配中可能出现的溢出。

现在简单多了。@KerrekSB:Link?解释?也许看看下面的分配器示例,用
malloc
/
free
。@KerrekSB:那么,不再有
construct()
?不,
construct
作为分配器特性的一部分,现在有了默认实现。如果需要它执行非默认操作(例如
作用域分配程序
所做的操作),则可以指定它。
分配
需要抛出错误;它不能返回null。
friend
声明和交叉类型赋值是无关的。如果(std::size_t(-1)/sizeof(t)将是一个好主意中分配
以避免缓冲区溢出。还有@T.C.说了些什么。@KerrekSB还没有。一些集装箱要求仍在POCMA中说明。同时,
总是等于
对于空的分配器已经是真的了。@Arnaud“可以有意义地传递给
分配
”的最大值与“可以传递给分配而不引起异常的最大值”不同。需求字面上说是
分配(max\u size()+2)
没有任何意义。@Elkvis没有;大小\u t保证为无符号,对于某些
n
,无符号保证为数学模
2^n
。因此,
无符号类型(-1)
始终是任何无符号类型的最大值。作为一个小小的奖励,它不需要在其中包含具有
数值限制的标准头文件。它应该是
std::numeric\u limits::max()
而不是
静态转换(-1)
尽管如此?@einpoklum标准保证是相同的:size\u不必遵守mod 2^N算法,其中N是size\u t的位数。使用后者而不是前者仍然是不好的编码方式。@einpoklum我同意。@einpoklum我认为
std::list
需要定义分配器的其他方法,如
重新绑定