首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

C++类的初始化列表是怎么一回事?哪些东西必须放在初始化列表中进行初始化,原因是什么?

  • 25-03-05 03:28
  • 2935
  • 14009
blog.csdn.net

目录

  • 01-C++类的初始化列表的概要介绍
    • 语法
    • 为什么使用初始化列表?
    • 示例代码
    • 小结
  • 02-初始化列表是写在构造函数的函数体之前的代码的
    • **1. 结构分析**
    • **2. 示例:基类 + 成员变量**
        • **输出**
    • **3. 初始化列表 vs 构造函数体**
      • **(1) 使用初始化列表**
      • **(2) 在构造函数体赋值**
  • 03-必须放在初始化列表中进行初始化的东西
    • 常量成员
    • 引用成员
    • 没有默认构造函数的类成员
    • 类的基类没有默认构造函数

01-C++类的初始化列表的概要介绍

在C++中,类的初始化列表是一个在构造函数体之前用来初始化类成员的机制。它允许你在构造函数的声明部分直接初始化成员变量,而不是在构造函数体内通过赋值的方式。

语法

初始化列表紧跟在构造函数名称之后,用冒号 : 开始,后面跟着成员变量的初始化。每个成员变量通过逗号 , 分隔。

class ClassName {
public:
    // 构造函数带有初始化列表
    ClassName(int a, int b) : x(a), y(b) {  // x和y分别通过初始化列表初始化
        // 其他构造函数体代码(如果有)
    }

private:
    int x, y;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

其中x(a)的意思并不是调用名叫x的函数,而是把成员变量x的值初始化a的值。同样,y(b)的意思也并不是调用名叫y的函数,而是把成员变量y的值初始化为b的值。

为什么使用初始化列表?

  1. 提高效率:通过初始化列表可以直接初始化类成员,而不是先调用默认构造函数再进行赋值操作。
  2. 有一些成员变量只能在初始化列表中进行初始化,具体如下:
    ①常量成员和引用成员:常量成员变量和引用成员必须通过初始化列表来初始化,因为它们无法在构造函数体内被赋值。至于为什么,请往后看,我在后面说明了原因。
    ②如果类型为类类型的成员变量【即某个类的实例对象】没有默认构造函数,也需要在初始化列表中进行初始化。关于什么叫默认构造函数,请看我的另一篇博文 [http://iyenn.com/rec/1709345.html]
  3. 如果一个类的基类没有使用默认构造函数,也需要在初始化列表进行初始化。关于什么叫默认构造函数,请看我的另一篇博文 http://iyenn.com/rec/1709345.html

示例代码

#include 
using namespace std;

class Rectangle {
public:
    // 带有初始化列表的构造函数
    Rectangle(int l, int w) : length(l), width(w) {
        // 构造函数体
        cout << "Rectangle created!" << endl;
    }

    // 打印矩形的面积
    void area() {
        cout << "Area: " << length * width << endl;
    }

private:
    int length, width;
};

int main() {
    Rectangle rect(10, 5);  // 创建一个长为10,宽为5的矩形
    rect.area();  // 打印矩形的面积
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

关键点:

  1. Rectangle(int l, int w) : length(l), width(w):初始化列表在这里将 length 和 width 直接初始化为传入的 l 和 w 参数的值。
  2. length 和 width 是在构造函数体内使用之前就已经初始化了,而不是在函数体内通过赋值。

小结

  • 初始化列表通过冒号 : 开始,直接在构造函数声明中初始化成员变量。
  • 它比在构造函数体内赋值更高效,尤其对于常量成员、引用成员或需要特殊初始化的成员非常有用。

02-初始化列表是写在构造函数的函数体之前的代码的

初始化列表(Initializer List)是写在构造函数的函数体 {} 之前,用于初始化成员变量和基类。它的语法如下:

ClassName::ClassName(参数列表) : 成员变量1(值1), 成员变量2(值2), 基类(值) {  
    // 构造函数体
}
  • 1
  • 2
  • 3

1. 结构分析

class Example {
    int a;
    double b;
public:
    Example(int x, double y)  // 构造函数
        : a(x), b(y)  // ✅ 初始化列表(在函数体 `{}` 之前)
    {
        // 构造函数体
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • : a(x), b(y) 是 初始化列表,用来初始化 a 和 b。其中 a(x)的意思并不是调用名叫a的函数,而是把成员变量a的值初始化x的值。同样,b(y)的意思也并不是调用名叫b的函数,而是把成员变量b的值初始化为y的值。

  • {} 内是构造函数体,在初始化列表执行完之后才会运行。


2. 示例:基类 + 成员变量

#include 

class Base {
public:
    Base(int x) { std::cout << "Base constructor: " << x << "\n"; }
};


class Derived : public Base {
    int a;
public:
    Derived(int x, int y)
        : Base(x), a(y)  // ✅ 初始化列表
    {
        std::cout << "Derived constructor: " << a << "\n";
    }
};


int main() {
    Derived d(10, 20);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
输出
Base constructor: 10
Derived constructor: 20
  • 1
  • 2

流程

  1. 先执行初始化列表
    • Base(x) 先调用 Base 的构造函数,输出 "Base constructor: 10"。
    • a(y) 赋值给成员变量 a,即把y的值传递给成员变量a,注意这里不是调用函数名为a的函数。
  2. 然后执行构造函数体 {}
    • 输出 "Derived constructor: 20"。

上面代码中类Derived在定义时继续了基类Base,那么请问public Base中public的意思是什么?
答案见:http://iyenn.com/rec/1709346.html


3. 初始化列表 vs 构造函数体

(1) 使用初始化列表

class Example {
    int x;
public:
    Example(int value) : x(value) {}  // ✅ 直接初始化
};
  • 1
  • 2
  • 3
  • 4
  • 5

(2) 在构造函数体赋值

class Example {
    int x;
public:
    Example(int value) { x = value; }  // 在构造函数中赋值,不推荐
};
  • 1
  • 2
  • 3
  • 4
  • 5

✅ 推荐使用初始化列表,避免在构造函数中赋值,从而提高效率。


03-必须放在初始化列表中进行初始化的东西

常量成员

由于C++规定,所有成员变量必须在对象构造完成前初始化。而常量成员在初始化后不能修改,所以只能用初始化列表进行初始化。例子如下:

   class Test {
       const int x;
   public:
       Test(int val) : x(val) {} // 常量成员x必须用初始化列表进行初始化,否则编译错误
   };
  • 1
  • 2
  • 3
  • 4
  • 5

引用成员

关于引用成员为什么也必须在初始化列表中进行初始化,详情见 http://iyenn.com/rec/1709347.html
其实原因也和常量成员差不多,只是你需要了解下C++的引用成员是怎么回事儿。
例子如下:

   class Test {
       int& ref; // ref是一个引用类型的成员
   public:
       Test(int& r) : ref(r) {} // ref必须用初始化列表进行初始化
   };
  • 1
  • 2
  • 3
  • 4
  • 5

没有默认构造函数的类成员

如果某个成员变量的类型为类类型,即这个成员变量是一个类的对象实例,而这个类又没有默认构造函数,那么也需要在初始化列表中进行初始化。
详情见 http://iyenn.com/rec/1709345.html

类的基类没有默认构造函数

如果一个类的基类没有使用默认构造函数,也需要在初始化列表进行初始化。详情请请看我的另一篇博文 http://iyenn.com/rec/1709345.html

昊虹嵌入式技术交流群
QQ群名片
注:本文转载自blog.csdn.net的昊虹AI笔记的文章"https://blog.csdn.net/wenhao_ir/article/details/145422254"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top