c++ - 區分兩個零參數構造函數的慣用方式




performance constructor (5)

如果構造函數主體為空,則可以將其省略或默認設置:

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

然後 默認的初始化 event_counts counts; 會保留 counts.counts 未初始化(默認初始化為no-op),而 值初始化 event_counts counts{}; 將值初始化為 counts.counts ,有效地將其填充為零。

我有這樣的課:

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

};

然後,我將no-init構造函數稱為 event_counts c(uninit_tag{}); 當我想抑制施工時。

我對不涉及創建啞類或以某種方式更有效的解決方案持開放態度。


您可能要考慮對類進行 兩階段初始化

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()


我喜歡你的解決方案。 您可能還考慮了嵌套的struct和static變量。 例如:

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 {
    uint64_t counts[MAX_COUNTERS];

    event_counts() : counts{} {}
    event_counts(uninit_tag) {}
};    

struct event_counts_no_init: event_counts {
    event_counts_no_init(): event_counts(uninit_tag{}) {}
};

您可以通過將未初始化的構造函數的參數更改為 boolint 或其他內容來擺脫虛擬類,因為它不再需要助記符了。

您還可以交換繼承關係,並使用其答案中建議的默認構造函數(如Evg)定義events_count_no_init,然後將events_count作為子類:

struct event_counts_no_init {
    uint64_t counts[MAX_COUNTERS];
    event_counts_no_init() = default;
};

struct event_counts: event_counts_no_init {
    event_counts(): event_counts_no_init{} {}
};

我認為枚舉比標記類或布爾值更好。 您不需要傳遞一個結構實例,並且從調用方很明顯您將獲得哪個選項。

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




constructor