C++ 我需要C++;数组类模板,固定大小,基于堆栈,不';不需要默认构造函数

C++ 我需要C++;数组类模板,固定大小,基于堆栈,不';不需要默认构造函数,c++,arrays,constructor,default,stack-based,C++,Arrays,Constructor,Default,Stack Based,所以,我一直在研究boost::array,但它确实需要定义默认构造函数。 我认为用数据填充这个数组的最好方法是通过push_-back(const T&)方法。调用它的次数超过大小(编译时已知)将导致断言或异常,具体取决于构建配置。这样,它将始终包含有意义的数据。 有人知道这个概念的高效、可移植、可靠的实现吗?在C++0x中,您得到了std::array(可能与boost::array相同)。您可以使用fill()或std::fill\n()初始化数组数据: std::数组; 数组填充(0);

所以,我一直在研究boost::array,但它确实需要定义默认构造函数。 我认为用数据填充这个数组的最好方法是通过push_-back(const T&)方法。调用它的次数超过大小(编译时已知)将导致断言或异常,具体取决于构建配置。这样,它将始终包含有意义的数据。
有人知道这个概念的高效、可移植、可靠的实现吗?

在C++0x中,您得到了
std::array
(可能与boost::array相同)。您可以使用
fill()
std::fill\n()
初始化数组数据:

std::数组;
数组填充(0);
阵列弹幕;
std::fill_n(barray.begin(),30,0);
如果要在定义处对其进行默认初始化,可以使用copy-ctor:

static std::array<int, 30> const nullarray = {0, 0, 0, ..., 0}; // nullarray.fill(0);
// (...)
std::array<int, 30> array{nullarray};
static std::array const nullarray={0,0,0,…,0};//nullarray.fill(0);
// (...)
std::数组{nullarray};
boost::阵列ta
T[12]ta没有区别;如果不使用初始值设定项列表,则元素将默认构造

常见的解决方法是
boost::array ta或者可能
boost::array ta

按值存储的唯一方法是复制,无法绕过这一点。。。初始化列表就是这样做的:

struct A {
    A(int i):_i(i){ cout << "A(int)" << endl; }
    A(const A& a){ cout << "A(const A&)" << endl; }
    ~A(){ cout << "~A()" << endl; }

    int _i;
};

int main(){
    boost::array<A, 2> ta = {{1, 2}};
}

为什么它必须驻留在堆栈上?您是否有经验证据表明创建和保留
向量
太慢(使用
向量
似乎是显而易见的答案)


即使是这样,您也可以创建一个向量池,保留空间,并将预先分配的向量之一交换到本地副本中。当您使用完本地一个后,再次将其交换回来(非常类似于
列表的
拼接技巧)。

是否可以在boost::数组中存储boost::variant?将第一个参数设为int或其他

i、 e

boost::数组条;

好的,你必须处理一个变体,但它是堆栈分配的…

好吧,我原以为现在会有人带来答案,但似乎没有,所以我们走吧

您所希望的是我自己梦寐以求的东西:一个
boost::可选的_数组

有两种变体:

  • 第一:类似于
    boost::array
    ,即每个元素都可以设置,也可以不设置
  • 第二:与std::vector类似(不知何故),即所有开始元素都已设置,而后面的元素都未设置
鉴于前面的问题/评论,您似乎想要第二个,但这并不重要,因为两者都非常相似

template <typename T, size_t N>
class stack_vector
{
public:
  bool empty() const { return mSize == 0; }
  size_t size() const { return mSize; }
  size_t capacity() const { return N; }
  size_t max_size() const { return N; }

  T& operator[](size_t i) { return *(this->pfront() + i); }
  /// ...

private:
  T* pfront() const { return reinterpret_cast<T*>(&mStorage); }

  std::aligned_storage< N * sizeof(T), alignof(T) > mStorage;
  size_t mSize; // indicate how many elements are set, from the beginning
};
模板
类堆栈向量
{
公众:
bool empty()常量{return mSize==0;}
size_t size()常量{return mSize;}
size_t capacity()常量{return N;}
size\u t max\u size()常量{return N;}
运算符[](size_T i){return*(this->pfront()+i);}
/// ...
私人:
T*pfront()常量{return reinterpret_cast(&mStorage);}
标准:对齐的存储mStorage;
size\u t mSize;//指示从一开始设置了多少个元素
};
让我们关注那些非常特殊的行动:

template <typename T, size_t N>
void push_back(T const& t)
{
  new (this->pfront() + mSize) T(t); // in place construction
  ++mSize;
}

template <typename T, size_t N>
void clear()
{
  for (size_t i = 0; i != mSize; ++i)
  {
    (this->pfront() + i)->~T();
  }
  mSize = 0;
}
模板
无效推回(T const&T)
{
新建(this->pfront()+mSize)T(T);//就地构造
++mSize;
}
样板
无效清除()
{
对于(大小i=0;i!=mSize;++i)
{
(this->pfront()+i)->~T();
}
mSize=0;
}
正如您所注意到的,主要的困难在于记住:

  • 如果还没有在那里构建元素,则需要放置新的+复制构造,而不是赋值
  • 应该正确地处理“过时”(即在最后一个元素之后)的元素(即调用其析构函数)
在传统STL容器上有许多操作可能很难实现。在
向量
上,元素洗牌(由于
插入
擦除
)可能是最严格的例子


还请注意,使用C++0x和初始值设定项列表
vector
get
emplace\u-back
直接在适当的位置构造元素,从而取消
CopyConstructible
要求,这可能是一个很好的好处,具体取决于您的情况。

push\u-back
与“固定大小”相矛盾。我想我知道你的意思,它的大小有一个固定的上限,一旦你填充了它,你就不会改变它的大小。我不知道有这样的实现。你说的“不需要默认构造函数”是什么意思?
char array[5]
是固定大小的,可以模板化,并且是基于堆栈的。奖励:即使在
C
中也能工作:D@Steve:我想他的意思是他想要一个“固定容量”。@user467799:我猜一个
boost::array
不能满足您的要求?如果您使用的不是
int
而是用户定义的类型,那么所有30个都将默认构造(使用
fill
),这是OP不想要的。@joshperry:oh,这就是
不需要默认构造函数的意思;因此,问题不在于容器-然后OP需要将其默认的ctor删除或私有,例如,使用sfinae进行默认ctor检查否,这对我的需要来说是次优的。我想按值而不是地址在小数组中存储一些小对象。在某些情况下,使用初始值设定项列表可能会很麻烦。通过在一个地方更改编译时常数,您可以很容易地更改数组大小,但可能您必须在许多其他地方更改初始值设定项列表。我并没有说这不会很麻烦,我只是说这是做您想要的事情的唯一方法(除了另一个答案中推荐的不透明类型hack)。我没有否决,但在我看来,这将是一个很好的评论候选人。这是一个解决方案,但远非如此
boost::array<boost::variant<int, foo>, 6> bar;
template <typename T, size_t N>
class stack_vector
{
public:
  bool empty() const { return mSize == 0; }
  size_t size() const { return mSize; }
  size_t capacity() const { return N; }
  size_t max_size() const { return N; }

  T& operator[](size_t i) { return *(this->pfront() + i); }
  /// ...

private:
  T* pfront() const { return reinterpret_cast<T*>(&mStorage); }

  std::aligned_storage< N * sizeof(T), alignof(T) > mStorage;
  size_t mSize; // indicate how many elements are set, from the beginning
};
template <typename T, size_t N>
void push_back(T const& t)
{
  new (this->pfront() + mSize) T(t); // in place construction
  ++mSize;
}

template <typename T, size_t N>
void clear()
{
  for (size_t i = 0; i != mSize; ++i)
  {
    (this->pfront() + i)->~T();
  }
  mSize = 0;
}