C++之初始化列表

本文介绍了C++中构造函数体赋值的区别于初始化列表的使用,重点讲解了如何在类中正确运用初始化列表来初始化对象,以及explicit关键字在单参构造函数中的作用。通过实例说明了避免隐式类型转换的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

一、构造函数体赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};

虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称作为类对象成员的初始化,构造函数体中的语句只能将其称作为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。

二、初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

class Date
{
	
public:
	
	Date(int year = 1, int month = 1, int day = 1)//带参数的构造函数
		:_year(1)//初始化列表
		,_month(1)
		,_day(1)
	{}
	
	
	Date(const Date& d)//拷贝构造函数
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	
private:
	int _year;
	int _month;
	int _day;
};

注意:

  1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
  2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
    引用成员变量
    const成员变量
    自定义类型成员(该类没有默认构造函数)
class A
{
public:
A(int a)
:_a(a)
{}
private:
int _a;
};
class B
{
public:
B(int a, int ref)
:_aobj(a)
,_ref(ref)
,_n(10)
{}
private:
A _aobj; // 没有默认构造函数
int& _ref; // 引用
const int _n; // const
};
  1. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
  2. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关

3.explicit关键字

构造函数不仅可以构造与初始化对象,对于单个参数的构造函数,还具有类型转换的作用。
列如:

class Date
{
public:
explicit Date(int year)
:_year(year)
{}
 Date(int year)
:_year(year)
{}
private:
int _year;
int _month:
int _day;
}void TestDate()
{
Date d1(2018);
// 用一个整形变量给日期类型对象赋值
// 实际编译器背后会用2019构造一个无名对象,最后用无名对象给d1对象进行赋值
d1 = 2019;
// 上述类型含有隐式类型转换 “d1= 2019” 相当于 “Date d2(2019); Date d1(d2)”
//编译器自动将整型转换为Date类对象
}

上述代码可读性不是很好,用explicit修饰构造函数,将会禁止单参构造函数的隐式转换。
explicit的详细理解

总结

以上就是关于初始化列表的全部内容,感谢大家的观看

<think>我们正在讨论C++中结构体的初始化列表用法。根据引用内容,初始化列表C++11之后被广泛支持,可以用于数组、向量、结构体等类型的初始化。在结构体中,我们可以使用花括号{}进行初始化,这被称为统一初始化列表初始化。引用[2]提到,使用{}初始化结构体时,会对每个成员进行值初始化。对于基本类型,会初始化为0或等价形式;对于类类型,会调用默认构造函数。引用[4]展示了结构体使用构造函数和初始化列表的两种方法。其中,构造函数后的初始化列表用于初始化成员变量。引用[5]指出,使用初始化列表时不能跳过前面的成员,必须按照顺序初始化,但可以省略尾部成员(这些尾部成员将被默认初始化)。用户要求的是结构体初始化列表的用法和示例。这里需要区分两种初始化列表:1.结构体对象的初始化列表:在定义结构体变量时使用花括号{}初始化成员。2.结构体构造函数中的成员初始化列表:在结构体的构造函数中,使用冒号后面的列表初始化成员。根据引用内容,我们可以提供两种用法的示例。示例1:使用花括号初始化结构体对象(统一初始化)示例2:在结构体的构造函数中使用成员初始化列表此外,引用[3]提到,C++11之前不能在结构体声明中直接初始化成员,但C++11允许非静态成员变量在声明时进行初始化(即提供默认值)。不过用户的问题集中在初始化列表上,所以我们主要展示初始化列表的使用。下面给出示例代码:</think>### C++结构体初始化列表用法详解 在C++中,结构体初始化列表主要包含两种形式:**统一初始化(花括号{})** 和 **构造函数成员初始化列表**。以下是具体用法和示例: #### 1. 统一初始化(花括号{}) C++11引入的统一初始化语法,可直接用花括号初始化结构体成员: ```cpp struct Point { int x; int y; double z; }; // 完全初始化 Point p1 = {3, 4, 1.5}; // x=3, y=4, z=1.5 // 部分初始化(尾部成员可省略) Point p2 = {5, 6}; // x=5, y=6, z=0.0(自动零初始化) // 错误示例:不能跳过中间成员 // Point p3 = {7, , 2.0}; // 编译错误! ``` **特性**: - 成员按声明顺序初始化[^5] - 未指定成员自动零初始化(基本类型为0,类类型调用默认构造函数)[^2] - 支持嵌套结构体初始化: ```cpp struct Line { Point start; Point end; }; Line l = { {1,2}, {3,4} }; // 嵌套初始化 ``` #### 2. 构造函数成员初始化列表 在结构体内部定义构造函数时使用: ```cpp struct Student { std::string name; int id; double gpa; // 无参构造(成员初始化列表) Student() : name("Unknown"), id(0), gpa(0.0) {} // 带参构造 Student(std::string n, int i, double g) : name(n), id(i), gpa(g) {} // 初始化列表 }; // 使用示例 Student s1; // 调用无参构造 Student s2 = {"Alice", 101, 3.8}; // 统一初始化 Student s3("Bob", 102, 3.9); // 直接调用构造函数 ``` **关键点**: - 初始化顺序由成员声明顺序决定,与列表顺序无关 - 避免"未初始化成员"错误,尤其用于结构体数组[^4] - C++11起支持非静态成员在声明处直接初始化: ```cpp struct Book { std::string title = "Untitled"; // C++11允许 int pages = 0; }; ``` #### 3. 组合初始化技巧 ```cpp // 声明时默认值 + 构造函数初始化列表 struct Widget { int id = -1; std::string name; Widget(int i, std::string n) : id(i), name(n) {} }; // 统一初始化与构造函数混用 Widget w1{10, "Gadget"}; // 调用构造函数 Widget w2{}; // id=-1, name="" ``` **注意事项**: 1. C++11前不能在结构体声明中初始化成员[^3] 2. 使用`{}`初始化可避免"最令人烦恼的解析"问题 3. 部分初始化时,省略的成员必须位于尾部[^5] 4. 初始化列表优先于类内初始值(构造函数中显式初始化会覆盖声明时的默认值) > 完整示例:[Compiler Explorer](https://godbolt.org/z/8f5n5G3vK)
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1无名之辈1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值