![](/img/trans.png)
[英]How do you create a template definition for a fixed-size array class in 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
,元素改組(由於insert
或erase
)可能是最引人注目的例子。
還要注意,使用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()
可能在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
到本地副本中。 完成本地操作后,再次將其交換回去(很像list
的splice
技巧)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.