1 指派初始化器
C++20引入了指派初始化器,以使用他们的名称初始化所谓聚合的数据成员。
聚合类型是满足以下限制的数组类型的对象或结构或类的对象:
1.仅public数据成员,
2.无用户声明或继承的构造函数,
3.无虚函数和无虚基类、private或protected的基类
指派初始化的顺序必须与声明顺序相同,不允许混合使用指派初始化器和非指派初始化器。未使用指派初始化器初始化的任何数据成员都将使用其默认值进行初始化,这意味着:
拥有类内初始化器的数据成员会得到该值
没有类内初始化器的数据成员会被零初始化
例如:
struct Employee{
char firstInitial;
char lastInitial;
int employeeNumber;
int salary{75000};
}
用统一初始化语法初始化:
Employee anEmployee{'J','D',42 ,80'000};
使用指派初始化器:
Employee anEmployee{
.firstInitial = 'J',
.lastInitial = 'D',
.employeeNumber= 42,
.salary =80'000
};
省略的成员将调用零初始化,而有默认初始化的成员将按其默认值进行初始化。
2 指针
2.1 栈和自由存储区
C++程序中的内存分为两部分——栈(stack)和自由存储区(free store)。
自由存储区是与当前函数或栈帧完全独立的内存区域。必须确保释放(删除)在自由存储区上分配的任何内存,这个过程不会自动完成,除非使用了智能指针。
2.2 指针
int* myIntegerPointer;
所声明的变量引用/指向某个整数内存,如上未初始化会指向某个随机位置
int* myIntegerPointer{nullptr};
空指针是一个特殊的默认值,有效的指针都不含该值,在布尔表达式中使用时会被转换为false
使用new操作符分配内存:
myIntegerPointer = new int;
使用解引用访问:
*myIntegerPointer=8;
delete释放内存:
delete myIntegerPointer;
myIntegerPointer = nullptr;
也可以声明指向栈中变量甚至指向其他指针的指针:
int i {8};
int* myIntegerPointer{&i};
C++使用特殊语法处理指向结构体或类的指针:
“->”同时解引用并访问字段
Employee* anEmployee{getEmployee()};
cout<<(*anEmployee).salary<<endl;
//等价于
cout<<anEmployee->salary<<endl;
与指针一起使用:
bool isVaildSalary{(anEmployee!=nullptr && anEmployee->salary > 0 ) }
2.3 动态分配数组
int arraySize{8};
int* myVariableSizedArray{new int[arraySize]};
这种情况下指针变量仍然在栈中,但动态创建的数组在自由存储区中。
释放:
delete[] myVariableSizedArray;
myVariableSizedArray = nullptr;
2.4 const与指针
这两种写法都是无法更改ip指向的值
const int* ip;
ip=new int[10];
ip[4]=5;//Does not compile!
int const* ip;
ip=new int[10];
ip[4]=5;//Does not compile!
如果想将ip本身标记为const,而不是他指向的值,需要这样写:
int* const ip{nullptr};
ip=new int[10];//Does not compile!
ip[4]=5;
// 也可以初始化指向新分配的内存
int* const ip{new int[10]};
如果想本身和指向的值都标记为const,可以这样:
int const* const ip{nullptr};
const int* const ip{nullptr};