簡體   English   中英

我需要C ++數組類模板,該模板是固定大小的,基於堆棧的並且不需要默認構造函數

[英]I need C++ array class template, which is fixed-size, stack-based and doesn't require default constructor

因此,我一直在研究boost :: array,但它確實需要定義默認的構造函數。 我認為用數據填充該數組的最佳方法是通過push_back(const T&)方法。 調用它的次數超過SIZE(在編譯時已知)的次數將導致斷言或異常,具體取決於構建配置。 這樣,它將始終包含有意義的數據。 有誰知道這個概念的高效,可移植,可靠的實現?

好吧,我本來以為有人會帶來答案,但是似乎沒有,所以讓我們開始吧。

您所希望的是我自己夢of以求的東西: boost::optional_array<T,N>

有兩種變體:

  • 第一:類似於boost::array< boost::optional<T>, N > ,即可以設置或可以不設置每個元素。
  • 第二:類似於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;
}

如您所見,主要困難是要記住:

  • 如果尚未在此處構建任何元素,則需要放置新的+副本結構而不是分配。
  • 變得“過時”的元素(即在最后一個元素之后)應該被正確處理(即調用它們的析構函數)。

傳統STL容器上有許多操作可能難以實現。 vector ,元素改組(由於inserterase )可能是最引人注目的例子。

還要注意,使用C ++ 0x和initializer-lists vector可以使用emplace_back直接在適當位置構造一個元素,從而解除CopyConstructible要求,這可能取決於您的情況。

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

可能在boost :: array中存儲了boost :: variant? 將第一個參數設為int或其他內容。

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

好的,您必須處理一個變體,但是它已分配了堆棧...

在C ++ 0x中,您得到了std::array<type, size> (可能與boost :: array相同)。 您可以使用fill()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};

為什么它必須駐留在堆棧上? 您是否有經驗證據證明創建和reserve vector太慢(使用vector似乎是顯而易見的答案)?

即使是這樣,您也可以創建一個保留了空間的向量池,並將其中一個預先分配的向量swap到本地副本中。 完成本地操作后,再次將其交換回去(很像listsplice技巧)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM