什么是初始化列表?

初始化列表(Initializer List):是 C++ 中用于在对象构造时直接初始化成员变量的语法。

  • 它位于构造函数的参数列表之后,函数体之前,以冒号:开始,后面跟着用逗号分隔的成员变量初始化列表。
  • 它核心作用是在对象内存分配完成后立即初始化成员,而非先默认初始化再赋值。

代码语言:javascript

AI代码解释

class MyClass 
{
    int _a;
    double _b;
    std::string _s;
public:
    // 初始化列表语法
    MyClass(int a, double b, const std::string& s) 
        : _a(a), _b(b), _s(s)  // 初始化列表
    {
        // 构造函数体(此时成员已初始化)
    }
};
为什么要使用初始化列表?

使用初始化列表主要有以下两点原因:

  1. 为了提高类的成员变量的初始化效率
  2. 有些成员变量不得不使用初始化列表进行初始化

--------------------为了提高效率--------------------

对于类类型的成员变量 :

  • 如果没有使用初始化列表,在进入构造函数体之前,会先调用成员变量的默认构造函数进行初始化,然后在构造函数体中再进行赋值操作,这会产生额外的开销。
  • 而使用初始化列表,可以直接调用成员变量的合适构造函数进行初始化,避免了先默认构造再赋值的过程,从而提高了初始化效率。
    • 例如:当成员变量是string类型时,使用初始化列表可以直接调用string的构造函数来初始化,而不是先默认构造一个空字符串,再进行赋值。

代码语言:javascript

AI代码解释

class Student 
{
    string _name;
public:
    // 低效写法:先默认构造空字符串,再赋值
    Student(const std::string& name) 
    { 
        _name = name; 
    }
    
    // 高效写法:直接调用string的拷贝构造
    Student(const string& name) : _name(name) {}
};

--------------------不得不使用--------------------

初始化 const 成员和引用成员

  • const成员变量和引用成员在定义后就不能被修改,因此必须在定义时进行初始化。
  • 初始化列表是在构造函数中初始化const成员和引用成员的唯一方法。如果不使用初始化列表,试图在构造函数体中对const成员或引用成员进行赋值,将会导致编译错误。

代码语言:javascript

AI代码解释

----------------------------初始化 const 成员----------------------------
class ConstDemo 
{
    const int _value;
public:
    ConstDemo(int v) : _value(v) {} // 必须用初始化列表
};


----------------------------初始化 const 成员----------------------------
 class RefDemo 
{
    int& _ref;
public:
    RefDemo(int& r) : _ref(r) {} // 必须用初始化列表
};   

调用无默认构造的成员

  • 当成员变量的类没有默认构造函数,只有带参数的构造函数时,必须使用初始化列表来传递参数进行初始化。
  • 否则,编译器无法找到合适的构造函数来初始化成员变量,从而引发编译错误。

代码语言:javascript

AI代码解释

class Engine 
{
public:
    Engine(int power) {} // 只有带参构造
};
class Car 
{
    Engine _engine;
public:
    Car() : _engine(100) {} // 必须显式初始化
};
怎么使用初始化列表?

代码语言:javascript

AI代码解释

#include<iostream>
using namespace std;

// Time类定义
class Time
{
public:
    /*---------------Time类的构造函数(带参数)---------------*/
    // 注意:这个类没有提供默认构造函数(无参构造函数)
    Time(int hour)
        :_hour(hour)  
    {
        cout << "Time类的构造函数Time()" << endl; 
    }
private:
    int _hour; 
};


// Date类定义
class Date
{
public:
    /*---------------Date类的构造函数---------------*/
    Date(int& x, int year = 1, int month = 1, int day = 1)
        :_year(year)      // 初始化_year
        , _month(month)   // 初始化_month
        , _day(day)       // 初始化_day
        , _t(12)          // 初始化Time类成员(必须提供参数)
        , _ref(x)         // 初始化引用成员(必须通过初始化列表)
        , _n(1)           // 初始化const成员(必须通过初始化列表)
    {
        // 如果尝试在构造函数体内初始化以下成员,会导致编译错误:
        // 1. _t(12) - 错误:Time类没有默认构造函数
        // 2. _ref = x - 错误:引用必须在初始化列表中初始化
        // 3. _n = 1 - 错误:const成员必须在初始化列表中初始化
    }

    /*---------------打印日期信息---------------*/
    void Print() const
    {
        cout << _year << "-" << _month << "-" << _day << endl; //const成员函数,保证不会修改对象状态
    }

private:
    int _year;    
    int _month;   
    int _day;     
    Time _t;      // Time类成员(没有默认构造函数)
    int& _ref;    // 引用成员  (必须在初始化列表中初始化)
    const int _n; // const成员 (必须在初始化列表中初始化)
};

int main()
{
    int i = 0;  //定义一个整型变量用于初始化Date的引用成员

    // 创建Date对象d1
    // 参数:
    //   i - 用于初始化_ref引用成员
    //   其他参数使用默认值
    Date d1(i);

    // 调用Print方法输出日期信息
    d1.Print();

    return 0;
}

/*
 * 关键点总结:
 * 1. 初始化列表的必要性:
 *    - 必须用于初始化:引用成员(_ref)、const成员(_n)、没有默认构造函数的类成员(_t)
 *
 * 2. 初始化顺序:
 *    - 成员变量的初始化顺序由它们在类中的声明顺序决定(_year→_month→_day→_t→_ref→_n)
 *    - 与初始化列表中的书写顺序无关
 *
 * 3. 特殊成员初始化:
 *    - 引用和const成员:只能在初始化列表中初始化
 *    - 没有默认构造的类成员:必须在初始化列表中显式构造
 *
 * 4. 良好实践:
 *    - 即使对普通成员变量(如:_year)也使用初始化列表
 *    - 保持初始化列表顺序与成员声明顺序一致
 */

在这里插入图片描述

在这里插入图片描述

初始化列表 vs 构造函数体内赋值谁能获胜?

特性

初始化列表

构造函数内赋值

const成员

✔️ 支持

❌ 编译错误

引用成员

✔️ 支持

❌ 编译错误

无默认构造的成员

✔️ 支持

❌ 编译错误

性能

更高效(直接构造)

可能低效(先默认构造再赋值)

初始化顺序

由成员声明顺序决定

无顺序依赖

使用初始化列表的注意事项有哪些?

在 C++ 中,成员变量的初始化遵循两大规则:


其一:初始化顺序仅取决于变量在类中声明的先后次序,与初始化列表中的排列顺序无关。


 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐