对非对象使用成员初始值设定项列表不好吗

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

本文关键字:列表 对象 成员      更新时间:2023-10-16

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

就像我在这里所做的:

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

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

  • 我的代码是否会因此变得效率降低速度减慢
  • 它是否配置了某种不良做法
  • 有什么理由让我为写这样一段代码而鞭策自己吗

据我所知,使用成员(初始化器)列表(不使用"成员",初始化器列表指的是C++11中引入的另一个概念)通常被认为更好。如果没有它,我相信它最终会在构造函数主体中替换成员之前默认构造成员(可能取决于编译器/优化级别)。

作为支持,我向您介绍MSDN:

会员名单

通过使用成员初始值设定项列表,从构造函数参数初始化类成员。此方法使用直接初始化,这比在构造函数体内使用赋值运算符更有效。

关于cppreference(强调):

在构成构造函数函数体的复合语句开始执行之前,所有直接基、虚拟基和非静态数据成员的初始化都已完成成员初始值设定项列表是可以指定这些对象的非默认初始化的位置。对于无法默认初始化的成员,例如引用和常量限定类型的成员,必须指定成员初始值设定项。

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

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

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

对于非基本数据类型(generic类型可能是这种类型),它的效率可能会降低,尤其是在它们具有大量默认构造函数的情况下。这是因为,如果不使用初始值设定项列表,则使用默认构造函数创建对象,然后将为其分配一个新值,这可能会浪费默认构造函数所做的工作。

除非有特定的原因不这样做,否则我更喜欢始终使用初始化列表,以防它更高效。