أحتاج إلى قالب فئة صفيف C ++ ، وهو ثابت الحجم ، ويستند إلى المكدس ولا يتطلب مُنشئًا افتراضيًا
-
28-09-2019 - |
سؤال
لذلك ، لقد كنت أبحث في AROST :: Array ولكنه يتطلب تحديد مُنشئ افتراضي. أعتقد أن أفضل طريقة لملء هذه الصفيف بالبيانات ، ستكون من خلال طريقة push_back (const t &). إن تسميته مرات أكثر من الحجم (المعروف في وقت الترجمة) سيؤدي إلى تأكيد أو استثناء ، اعتمادًا على تكوين البناء. وبهذه الطريقة ستحتوي دائمًا على بيانات ذات مغزى. هل يعرف أي شخص تنفيذ فعال ومحمول وموثوق به لهذا المفهوم؟
المحلول
حسنًا ، كنت أعتقد أن شخصًا ما كان سيحضر الإجابة الآن ، ولكن يبدو أنه لا ، لذلك دعنا نذهب.
ما تتمناه هو شيء حلمت به: أ 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 و Pistumizer-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()
قد يكون تخزين دفعة :: البديل في دفعة :: صفيف؟ اجعل المعلمة الأولى int أو شيء من هذا القبيل ..
بمعنى آخر
boost::array<boost::variant<int, foo>, 6> bar;
حسنًا ، عليك أن تتعامل مع متغير ، لكنه مخصص ...
في C ++ 0x حصلت std::array<type, size>
(ربما نفس المعزز :: صفيف). يمكنك تهيئة بيانات الصفيف باستخدام 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
واحدة من المتجهات المسبقة مسبقا في نسخة محلية. عندما تنتهي مع واحد محلي ، قم بتبديله مرة أخرى (مثل إلى حد كبير splice
خدعة ل list
س).