区分两个零参数构造函数的惯用方式

Bee*_*ope 33 c++ performance constructor

我有这样的课:

struct event_counts {
    uint64_t counts[MAX_COUNTERS];

    event_counts() : counts{} {}

    // more stuff

};

Run Code Online (Sandbox Code Playgroud)

通常我想默认(零)初始化counts数组,如图所示。

但是,在通过性能分析确定的选定位置,我想抑制数组初始化,因为我知道数组即将被覆盖,但是编译器不够聪明,无法弄清楚它。

创建这样的“辅助”零参数构造函数的惯用而有效的方法是什么?

当前,我正在使用uninit_tag作为伪参数传递的标记类,如下所示:

struct uninit_tag{};

struct event_counts {
    uint64_t counts[MAX_COUNTERS];

    event_counts() : counts{} {}

    event_counts(uninit_tag) {}

    // more stuff

};
Run Code Online (Sandbox Code Playgroud)

然后,像event_counts c(uninit_tag{});想抑制构造时一样,调用no-init构造函数。

我对不涉及创建哑类或以某种方式更有效的解决方案持开放态度。

Joh*_*nck 31

您已经拥有的解决方案是正确的,并且正是我要查看您的代码时想要的解决方案。它尽可能高效,清晰和简洁。

  • 标准库中没有明显的选择。我不会在需要该功能的每个类中定义一个新标签-我会定义一个项目范围的`no_init`标签,并将其在需要的所有类中使用。 (9认同)
  • 我认为标准库具有用于区分迭代器和此类内容的男子气概的标签以及两个`std :: piecewise_construct_t`和`std :: in_place_t`。在这里似乎没有一个合理的选择。也许您想定义一个始终使用的类型的全局对象,因此您不需要在每个构造函数调用中都使用大括号。STL通过为std :: piecewise_construct_t使用[`std :: piecewise_construct`](https://en.cppreference.com/w/cpp/utility/piecewise_construct)来做到这一点。 (2认同)

Evg*_*Evg 7

如果构造函数主体为空,则可以将其省略或默认设置:

struct event_counts {
    std::uint64_t counts[MAX_COUNTERS];
    event_counts() = default;
};
Run Code Online (Sandbox Code Playgroud)

然后,默认初始化 event_counts counts;将保持counts.counts未初始化状态(默认初始化在此处为no-op),而值初始化 event_counts counts{};将为initialize值counts.counts,有效地将其填充为零。

  • 但是再一次,您必须记住要使用值初始化,并且OP希望默认情况下它是安全的。 (3认同)

doc*_*doc 6

我喜欢你的解决方案。您可能还考虑过嵌套结构和静态变量。例如:

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

};
Run Code Online (Sandbox Code Playgroud)

使用静态变量未初始化构造函数调用似乎更方便:

event_counts e(event_counts::uninit);
Run Code Online (Sandbox Code Playgroud)

您当然可以引入一个宏来节省打字并使其更具有系统性

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

struct event_counts {
    UNINIT_TAG
}

struct other_counts {
    UNINIT_TAG
}
Run Code Online (Sandbox Code Playgroud)