C++构造函数初始化列表全解析

构造函数初始化列表

时间线:

  1. 调用构造函数 Example obj(10)

  2. 进入构造函数前,所有数据成员已经分配内存

  3. const 成员 value 必须在此刻初始化(因为它不能改变)

  4. 进入构造函数体 { ... }

  5. 此时 value 如果还未初始化,就无法再初始化了

在进入构造函数体中,已经为成员变量分配了空间,所以const修饰的成员变量和引用变量需要使用初始化列表进行初始化

对于自定义成员变量如果不写初始化列表的话,就会走自定义成员变量的默认构造函数,如果没有默认的构造函数就会报错

总结下来有三种情况必须走初始化列表

  1. 引用成员变量
  2. const成员变量
  3. 自定义成员变量(该类没有默认的构造函数时)

尽量走初始化列表初始化,因为不管你是否使用初始化列表,对于自定义成员变量一定会调用初始化列表

成员变量在类中的声明顺序和在初始化列表中的先后顺序无关,建议初始化列表顺序和声明顺序一致

一些初始化和检查工作,初始列表不能做

explicit关键字

用expilicit修饰构造函数,将会禁止构造函数的隐式转换

a.单参数隐式类型转换

cpp 复制代码
class Date {
    int year, month, day;
public:
    explicit Date(int y) : year(y), month(1), day(1) {  // 防止隐式转换
        std::cout << "Date from year: " << year << std::endl;
    }
    
    Date(int y, int m, int d) : year(y), month(m), day(d) { }
};

void scheduleEvent(const Date& date) {
    std::cout << "Event scheduled" << std::endl;
}

int main() {
    Date d1(2024);           // ✅ 显式构造
    Date d2 = 2024;          // ❌ 编译错误(有 explicit)
    
    scheduleEvent(Date(2024));   // ✅ 显式转换
    // scheduleEvent(2024);      // ❌ 编译错误(有 explicit)
    
    Date d3(2024, 1, 1);     // ✅ 多参数构造
    return 0;
}

b.多参数隐式类型转换

cpp 复制代码
class Point {
    int x, y;
public:
    explicit Point(int a, int b) : x(a), y(b) { }  // C++11 支持
};

void drawPoint(const Point& p) {
    std::cout << "Drawing point" << std::endl;
}

int main() {
    Point p1(10, 20);           // ✅ 显式构造
    Point p2 = {10, 20};        // ❌ 编译错误(C++11,有 explicit)
    Point p3{10, 20};           // ✅ C++11 统一初始化
    
    drawPoint(Point(10, 20));   // ✅ 显式
    // drawPoint({10, 20});     // ❌ 编译错误(有 explicit)
    
    return 0;
}

static修饰的成员变量

用static修饰的成员变量,称之为静态成员变量,静态成员变量是全局变量,一定过要在类初始化,属于这个类的所有对象,不能给缺省值。

static成员变量不走初始化列表,因为它属于整个类,而非某个实例的全局静态变量,声明和定义要分离

cpp 复制代码
class A
{
public:
	A() { _a++; }
	~A() { _a--; }
	A(const A& a) { ++_a; }
	static void Print()
	{
		std::cout << _a << std::endl;
	}
private:
	static int _a;//所有的实例共享一个静态成员变量
};


int A::_a = 0;//定义和声明分离
int main()
{
	A::Print();
	A a1, a2;
	A a3(a1);
	A::Print();

	return 0;
}

特点

  • 静态成员变量为所有的实例共享,存放在静态区
  • 静态成员变量必须要在类外定义,定义时候不添加static,类中只是声明
  • 静态成员变量可以通过类名::静态成员,对象.静态成员来访问
  • 静态成员也是类的成员,受public,protected,private访问限定符限制
  • 静态成员变量没有隐藏的this指针,不能访问任何非静态成员变量(逻辑上来说,选择不了访问哪个实例的成员)
相关推荐
嘿BRE17 小时前
【C++】智能指针
c++
楼田莉子17 小时前
Linux学习之库的原理与制作
linux·运维·服务器·c++·学习
浅念-17 小时前
C++第一课
开发语言·c++·经验分享·笔记·学习·算法
charlie11451419117 小时前
现代嵌入式C++教程:对象池(Object Pool)模式
开发语言·c++·学习·算法·嵌入式·现代c++·工程实践
HABuo17 小时前
【linux进程控制(三)】进程程序替换&自己实现一个bash解释器
linux·服务器·c语言·c++·ubuntu·centos·bash
一只小bit18 小时前
Qt 多媒体:快速解决音视频播放问题
前端·c++·qt·音视频·cpp·页面
凯子坚持 c18 小时前
C++大模型SDK开发实录(二):DeepSeek模型接入、HTTP通信实现与GTest单元测试
c++·http·单元测试
uoKent18 小时前
c++中的运算符重载
开发语言·c++
量子炒饭大师18 小时前
【C++入门】面向对象编程的基石——【类与对象】基础概念篇
java·c++·dubbo·类与对象·空指针规则
MSTcheng.18 小时前
【C++】链地址法实现哈希桶!
c++·redis·哈希算法