【C++语法】构造函数初始化列表

初始化列表相较于在构造函数体中赋值,有以下几个优势:

1. 避免多次构造

对于某些类型的成员变量(如 const 或引用类型),它们必须在初始化列表中进行初始化,不能在构造函数体中赋值。例如:

class Example {
    private:
       const int a; // 常量成员
       int& ref; // 引用成员
    public:
       Example(int x, int& y) : a(x), ref(y) {} // 初始化列表初始化
};

如果不使用初始化列表,常量或引用无法被赋值,因为它们必须在对象构造时完成初始化。


2. 提高性能

初始化列表直接初始化成员变量,而在构造函数体中赋值会导致先默认构造,再赋值的开销。例如:

class MyClass {
    std::string name;
    public:
       MyClass(const std::string& str) : name(str) {} // 直接初始化
       // 等价于 MyClass(const std::string& str) { name = str; }
};

差异:

  • 初始化列表:name(str) 会直接调用 std::string 的拷贝构造函数。
  • 构造函数体赋值:name 会先调用默认构造函数,然后再通过 = 调用拷贝赋值运算符,这多了一次默认构造的开销。

3. 简洁和可读性

使用初始化列表可以让代码更清晰,特别是在类中有多个成员需要初始化时:

class Point {
    private:
      int x, y;
    public:
      Point(int a, int b) : x(a), y(b) {} // 初始化列表方式,简洁明了
};

如果不用初始化列表,则需要在构造函数体内初始化:

class Point {
    private:
      int x, y;
    public:
      Point(int a, int b) { x = a; y = b; }
};

虽然效果相同,但代码冗长,且对复杂类型效率较低。


初始化列表的使用限制

  1. 必须初始化常量和引用类型

    • 常量和引用类型在声明后必须初始化,不能在构造函数体中赋值。
  2. 初始化顺序与成员声明顺序一致: 即使初始化列表中顺序不同,初始化的实际顺序始终以成员声明的顺序为准。例如:

    class Test {
        int a;
        int b;
      public:
        Test() : b(2), a(1) {} // 实际初始化顺序为 a -> b
    };

    如果 b 依赖于 a,这种写法可能会导致错误。

posted @ 2024-11-24 22:03  朝槿yys  阅读(11)  评论(0编辑  收藏  举报