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指针,不能访问任何非静态成员变量(逻辑上来说,选择不了访问哪个实例的成员)
相关推荐
梵尔纳多2 小时前
初识 OpenGL
c++·图形渲染
王老师青少年编程2 小时前
2025年12月GESP(C++二级): 黄金格
c++·算法·gesp·csp·信奥赛·二级·黄金格
一起搞IT吧2 小时前
相机Camera日志实例分析之十二:相机Camx【萌拍后置zoom拍照】单帧流程日志详解
android·c++·数码相机·智能手机
十五年专注C++开发2 小时前
浅谈Qt中的QSql模块整体设计
开发语言·数据库·c++·qt
k***92162 小时前
C++:继承
java·数据库·c++
咔咔咔的3 小时前
756. 金字塔转换矩阵
c++
fqbqrr3 小时前
2601,C++的模块2
c++
星轨初途3 小时前
C++ string 类详解:概念、常用操作与实践(算法竞赛类)
开发语言·c++·经验分享·笔记·算法
Lucis__3 小时前
哈希实现&封装unordered系列容器
数据结构·c++·算法·哈希封装