1

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

4

5 回答 5

1

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

你想要的是我自己梦寐以求的东西:a boost::optional_array<T,N>

有两种变体:

  • 第一:类似于boost::array< boost::optional<T>, N >,即每个元素都可以设置也可以不设置。
  • 第二:类似于a std::vector<T>(不知何故),即所有开始元素都已设置,而所有后续元素均未设置。

鉴于之前的问题/评论,您似乎想要第二个,但这并不重要,因为两者非常相似。

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;
}

如您所见,主要困难是要记住:

  • 如果那里还没有构建元素,则需要放置 new + 复制构造而不是赋值。
  • 变得“过时”的元素(即在最后一个元素之后)应该被正确处理(即它们的析构函数被调用)。

传统 STL 容器上有许多操作可能难以实现。在 a 上vector,元素改组(由于insertor erase)可能是最引人注目的例子。

另请注意,使用 C++0x 和初始化器列表vector可以emplace_back直接在适当位置构造一个元素,从而提高CopyConstructible要求,这可能是一个不错的好处,具体取决于您的情况。

于 2010-10-07T06:28:20.550 回答
0

boost::array<T, 12> ta;T[12] ta;和没有什么不同 如果你不使用初始化列表,那么元素将被默认构造。

常见的解决方法是boost::array<T*, 12> ta;或可能是boost::array<unique_ptr<T>, 12> 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}};
}

这输出:

A(int)
A(const A&)
A(int)
A(const A&)
~A()
~A()
~A()
~A()

http://codepad.org/vJgeQWk5

于 2010-10-06T14:51:25.330 回答
0

可能在你的 boost::array 中存储一个 boost::variant?使第一个参数为 int 或其他东西..

IE

boost::array<boost::variant<int, foo>, 6> bar;

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

于 2010-10-06T15:48:24.997 回答
-1

在 C++0x 中你得到了std::array<type, size>(可能与 boost::array 相同)。您可以使用fill()or初始化数组数据std::fill_n()

std::array<int, 30> array;
array.fill(0);
boost::array<int, 30> barray;
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};
于 2010-10-06T14:50:03.057 回答
-1

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

即使是这样,您也可以创建一个保留空间的向量池,并将swap其中一个预分配的向量放入本地副本。当你用完本地的后,再把它换回来(很像 s 的splice技巧list)。

于 2010-10-06T15:18:08.800 回答