使用自定义分配器调整大小

时间:2014-10-24 07:54:11

标签: c++ containers std

如何使用自定义分配器而不是复制构造函数来调整std :: vector的大小?

以下是我的尝试:

#include <vector>
#include <iostream>

class A{
public:
  A(int x){
    std::cout<<" new a:"<<this<<" "<< x<<std::endl;
  }
};

template<typename T>
class ParamAlloc:public std::allocator<T>{
public:
  template<typename U> struct rebind {typedef ParamAlloc other;};

  void construct(typename std::allocator<T>::pointer p, typename std::allocator<T>::const_reference val){
    new ((void*)p) T(47);
  }


  void destroy(typename std::allocator<T>::pointer p){
    ((T*)p)->~T();
  }
};


int main(){

  ParamAlloc<A> all;
  std::vector<A,ParamAlloc<A> > ac(all);
  ac.resize(5);
}

但由于编译尝试实例化A :: A(),我仍然遇到编译错误。

与此问题相关,分配A类对象向量的最佳方法(前C ++ 11)是什么,其中A的构造函数采用参数,但A对象不应复制构造

3 个答案:

答案 0 :(得分:3)

Pre-C ++ 11 resize成员定义为:

resize(size_type n, const T& = T());

因此,当您将其称为ac.resize(5)时,实际上意味着ac.resize(5, A())显然需要默认构造函数。 C ++ 03的唯一解决方法是提供一个要复制的对象:ac.resize(5, A(99)),它表示调整向量的大小并将任何新元素构造为A(99)的副本。副本将由您的自定义分配器完成,它实际上将它们构造为A(47),而不是使用复制构造函数。

C ++ 11放宽了对resize()的要求,而[vector.capacity]中的C ++ 11标准说vector::resize()

  

要求: T应为MoveInsertableDefaultInsertable*this

DefaultInsertable要求这是有效的:

allocator_traits<A>::construct(m, p)

该调用将尝试在分配器m.construct(p)上调用m,如果该调用有效,但是因为您的分配器不支持它将执行:

 ::new((void *)p) T()

需要默认构造函数。

如果您希望将自定义分配器用于resize,则需要提供一个只能使用一个参数调用的construct成员,例如

void construct(typename std::allocator<T>::pointer p){
  new ((void*)p) T(47);
}

这应该意味着在调整大小时不需要默认构造函数。

答案 1 :(得分:0)

只需为A(int x)提供默认参数,该组合将通过。

class A{
public:
  A(int x=0){//here !! 
    std::cout<<" new a:"<<this<<" "<< x<<std::endl;
  }
};

结果是:

 new a:0x7fffe01aab5f 0
 new a:0x1c7d010 47
 new a:0x1c7d011 47
 new a:0x1c7d012 47
 new a:0x1c7d013 47
 new a:0x1c7d014 47

答案 2 :(得分:0)

C ++标准定义了给定容器的项类型的某些要求。 例如,可以在C ++ 11 T must meet the requirements of CopyAssignable and CopyConstructible之前的向量中存储。要调整大小,请T must meet the requirements of DefaultConstructible。因此,前C ++ 11标准明确禁止您尝试实现的目标。也许你使用vector::reserve代替vector::resize就足够了,或者你只需​​要一个不同的容器。这在C ++ 11中是可能的 - 请参阅Jonathan Wakely的回答。