对非对象使用成员初始化列表不好吗?

Is it bad to use member initializer list for non-objects?

因为在某些情况下我只需要使用初始化列表,所以我养成了在构造函数仅用于设置成员值时将所有内容都放在初始化列表中的习惯。

就像我在这里做的那样:

template <typename generic>
class setsPool
{
    protected:

    set<generic> *pool;
    size_t maxSets;
    generic maximumValue, minimumValue;

    public:

    setsPool() = delete;

    explicit setsPool( size_t maxSets ) :
        pool(new set<generic>[maxSets]), maxSets(maxSets), 
        maximumValue(0), minimumValue(0) {}

    setsPool( size_t maxSets, generic minimumValue, generic maximumValue ) :
        pool(new set<generic>[maxSets]), maxSets(maxSets), 
        minimumValue(minimumValue), maximumValue(maximumValue) {}

    // ...
};

而不是这样做:

template <typename generic>
class setsPool
{
    // ... same stuff

    public:

    setsPool() = delete;

    explicit setsPool( size_t maxSets )
    {
        this->pool = new set<generic>[maxSets]);
        this->maxSets = maxSets; 
        this->maximumValue = minimumValue = 0;
    }

    setsPool( size_t maxSets, generic minimumValue, generic maximumValue )
    {
        this->pool = new set<generic>[maxSets]);
        this->maxSets = maxSets;  
        this->maximumValue = maximumValue;
        this->minimumValue = minimumValue;
    }

    // ...
};

以这个 真实 代码为例,我想知道这样做是否有任何缺点(当我真的不使用初始化列表时 必须 ) 并且我在这里找到的关于初始化列表的问题似乎并没有说清楚它是否 在不必要的情况下使用它是错误的

据我所知,使用成员(初始化程序)列表(w/o "member",初始化程序列表指的是 different concept introduced in C++11)通常被认为更好。没有它,我相信它最终会默认构建成员,然后再在构造函数主体中替换它们(可能取决于 compiler/optimization 级别)。

作为支持,我给你指出 MSDN:

Member Lists

Initialize class members from constructor arguments by using a member initializer list. This method uses direct initialization, which is more efficient than using assignment operators inside the constructor body.

cppreference 上(强调已添加):

Before the compound statement that forms the function body of the constructor begins executing, initialization of all direct bases, virtual bases, and non-static data members is finished. Member initializer list is the place where non-default initialization of these objects can be specified. For members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified.

这意味着构造函数主体中的任何赋值都在重新分配已经(默认)构造的成员。

正如 Neil 所提到的,对于 POD 类型,如果未在成员初始化列表中指定,则它们不是默认构造的(例如设置为 0)。因此,如果您仅在构造函数主体中设置它们,则不会进行冗余初始化,但使用成员初始化列表也不会花费您任何费用。

对于指针、整数和浮点数等基本数据类型,这并不重要。分配所有这些集合的成本将使任何差异相形见绌,编译器可以轻松优化代码,因为构造和复制基本数据类型没有副作用。

对于您的 generic 类型可能属于的非基本数据类型,它的效率可能较低,尤其是当它们具有繁重的默认构造函数时。这是因为,如果您不使用初始化列表,对象将使用默认构造函数创建,然后将被分配一个新值,可能会浪费默认构造函数所做的工作。

除非有特殊原因,否则我更喜欢始终使用初始化列表,以防万一它更有效率。