c++的对象初始化
忍不住了,不得不吐槽一下,妈的,太复杂了,真难,搞得太复杂了,看不懂,看不懂,真的越来越复杂了,没有必要啊!
看得了头皮发麻,搞不明白,咱又不是干编译器的,投降了。 工程代码中,代码风格要保持简洁,可读性好,可维护性好,没事千万别整一些奇奇怪怪的初始化秀技术,别过度依赖语言特性与编译器特性,最简单就是最好的!
我摊牌了,看了两天没有彻底看明白,我放弃了。把我看明白的部分作一下笔记,免得后续忘记了又重复看,浪费时间。
C++的初始化方式
见链接:https://en.cppreference.com/w/cpp/language/initialization
- Value initialization, e.g. std::string s{};
- Direct initialization, e.g. std::string s("hello");
- Copy initialization, e.g. std::string s = "hello";
- List initialization, e.g. std::string s{'a', 'b', 'c'};
- Aggregate initialization, e.g. char a[3] = {'a', 'b'};
- Reference initialization, e.g. char& c = a[0];
只介绍一下值初始化与聚合初始化, 因为很常用,尤其是咱们初始化结构体对象时。
值初始化
使用空的{}
进行值初始化。(即然c++11已经引入了{}
, 咱们也就别使用()
了吧,也就提了)。
规则是这样的:
- if T is a class type with no default constructor or with a user-provided or deleted default constructor, the object is default-initialized;
- if T is a class type with a default constructor that is neither user-provided nor deleted (that is, it may be a class with an implicitly-defined or defaulted default constructor), the object is zero-initialized and then it is default-initialized if it has a non-trivial default constructor;
however, all known compilers come into case (2) when a non-deleted defaulted default constructor is selected by overload resolution, even if there is a user-provided default constructor, see Notes; - if T is an array type, each element of the array is value-initialized;
- otherwise, the object is zero-initialized.
我只记两点:
第一:当对一个类对象提供了默认构造函数时,进行值初始化时,会执行你提供的构造函数,如果你的构造函数内未对成员变量进行初始化,它们就是未初始化状态。
第二:当用户不提供任何构造函数时,编译器会生成默认的构造函数,进行值初始化时,会首先进行零初始化,然后再调用默认生成的构造函数(non-trivial时)。
聚合初始化
针对聚合体,会进行聚会初始化, 使用 {arg1, arg2, ...}的格式。
什么是聚合体,满足这些条件就是了:(V__V, 头大,详细见 该链接处)
- no private or protected direct (since C++17)non-static data members
- no user-declared constructors (until C++11)
- no user-provided constructors (explicitly defaulted or deleted constructors are allowed)(since C++11)(until C++17)
- no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)(since C++17)(until C++20)
- no user-declared or inherited constructors(since C++20)
- no virtual, private, or protected (since C++17) base classes
- no virtual member functions
- no default member initializers (since C++11) (until C++14)
聚合初始化的规则,详细见此处。 我只提取了下面几条对我有用的(我只用于初始化trival的结构体):
- 如果列表的参数个数大于实际要初始化项的数目, 编译报错。
- 如果列表的参数个数小于实际要初始化项的数目, 剩余初始化为0.
- 如果为空{}, 全部初始化为0.
强烈建议
- c++11已经引入了类内成员初始化, 尽可能使用class 类对象内成员初始化,多方便简洁啊! 其次使用初始化列表。如果类内的数据结构复杂,那就老老实实的定义好各种构造函数。
- 对于struct结构体, 很多情况下,往往都没有初始值,要对struct对象的所有成员进行零初值操作,退荐使用空{}, 如果对部分成员初始化,使用{初始值1, 初始值2 ...}的形式。
- 简洁永远是最好的,保持好的编程习惯!