c++ - الطريقة الاصطلاحية لتمييز اثنين من صانعي الصفر




performance constructor (5)

لدي فئة مثل هذا:

struct event_counts {
    uint64_t counts[MAX_COUNTERS];

    event_counts() : counts{} {}

    // more stuff

};

عادةً ما أرغب في الإعداد الافتراضي (صفر) لتهيئة مجموعة counts كما هو موضح.

ومع ذلك ، في المواقع المحددة التي تم تحديدها بواسطة التوصيف ، أود منع تهيئة المصفوفة ، لأنني أعلم أن المصفوفة على وشك الكتابة فوقها ، لكن المحول البرمجي ليس ذكيًا بدرجة كافية للتعرف عليها.

ما هي الطريقة الاصطلاحية والفعالة لإنشاء مثل هذا المنشئ الصفري "الثانوي"؟

حاليًا ، أستخدم uninit_tag فئة علامة يتم تمريرها كوسيطة وهمية ، مثل ذلك:

struct uninit_tag{};

struct event_counts {
    uint64_t counts[MAX_COUNTERS];

    event_counts() : counts{} {}

    event_counts(uninit_tag) {}

    // more stuff

};

ثم أدعو مُنشئ عدم البدء مثل event_counts c(uninit_tag{}); عندما أريد أن قمع البناء.

أنا منفتح على الحلول التي لا تنطوي على إنشاء فئة وهمية ، أو أكثر فعالية بطريقة أو بأخرى ، إلخ.


أعتقد أن التعداد هو اختيار أفضل من فئة علامات أو منطقي. لا تحتاج إلى تمرير مثيل للبنية ومن الواضح من المتصل الخيار الذي تحصل عليه.

struct event_counts {
    enum Init { INIT, NO_INIT };
    uint64_t counts[MAX_COUNTERS];

    event_counts(Init init = INIT) {
        if (init == INIT) {
            std::fill(counts, counts + MAX_COUNTERS, 0);
        }
    }
};

ثم يبدو إنشاء مثيلات كما يلي:

event_counts e1{};
event_counts e2{event_counts::INIT};
event_counts e3{event_counts::NO_INIT};

أنا أحب الحل الخاص بك. ربما تكون قد فكرت أيضًا في بنية متغيرة ومتغيرة ثابتة. فمثلا:

struct event_counts {
    static constexpr struct uninit_tag {} uninit = uninit_tag();

    uint64_t counts[MAX_COUNTS];

    event_counts() : counts{} {}

    explicit event_counts(uninit_tag) {}

    // more stuff

};

مع متغير ثابت غير مهيأ منشئ دعوة قد يبدو أكثر ملاءمة:

event_counts e(event_counts::uninit);

يمكنك بالطبع تقديم ماكرو لحفظ الكتابة وجعلها أكثر من ميزة منهجية

#define UNINIT_TAG static constexpr struct uninit_tag {} uninit = uninit_tag();

struct event_counts {
    UNINIT_TAG
}

struct other_counts {
    UNINIT_TAG
}

إذا كان نص المنشئ فارغًا ، فيمكن حذفه أو تعطيله:

struct event_counts {
    std::uint64_t counts[MAX_COUNTERS];
    event_counts() = default;
};

ثم التهيئة الافتراضية event_counts counts; سيترك counts.counts غير مهيأ (التهيئة الافتراضية هي المرجع هنا) ، وتهيئة قيمة event_counts counts{}; سوف قيمة تهيئة counts.counts ، وملء بشكل فعال مع الأصفار.


الحل الذي لديك بالفعل صحيح ، وهو بالضبط ما أريد أن أشاهده إذا كنت أراجع الرمز. أنها فعالة قدر الإمكان ، واضحة وموجزة.


قد ترغب في النظر في تهيئة مرحلتين للفصل الدراسي:

struct event_counts {
    uint64_t counts[MAX_COUNTERS];

    event_counts() = default;

    void set_zero() {
       std::fill(std::begin(counts), std::end(counts), 0u);
    }
};

لا يقوم المنشئ أعلاه بتهيئة الصفيف إلى الصفر. لتعيين عناصر الصفيف إلى صفر ، يجب عليك استدعاء دالة العضو set_zero() بعد الإنشاء.





constructor