文章目录
- 类的大小及空类
- 构造拷贝构造的优化
- 初始化列表、匿名对象、类型的销毁顺序
- 隐式类型转换、静态关键字详解
- 输入输出操作符及重载、友元函数及类
- 内部类
- New、Delete、内存布局
- 在堆上申请4G的内存
- 内存泄漏的危害和防止
- 跑题是不存在的
类的大小及空类
- 一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类。
构造拷贝构造的优化
- 当有临时对象产生时,构造拷贝构造连续发生,编译器会直接优化中间步骤1-》3
初始化列表、匿名对象、类型的销毁顺序
- 匿名对象,生命周期旨在这一行A()
- 析构函数顺序分析
- 栈帧压栈后进先出
- 全局和静态的区别
- 全局在main函数之前就初始化了
- 静态是在 第一次调用域函数的时候 初始化
- 先释放静态,再释放全局**
- 初始化列表初始化,提高效率,可认为是成员变量初始化的地方,强制的有:引用 强制,自定义类型成员
- 双向带头循环的例子- 和声明的次序有关
ListNode(int x)
:val(x)
, next(nullptr)
{
cout << "ListNode()" << endl;
}
隐式类型转换、静态关键字详解
- 隐式类型转换,内置类型转换成自定义类型,先用内置类型创建一个匿名对象,再用匿名对象拷贝构造给另一个对象,中间优化了。C++11支持多个参数,explicit关键字可以阻止。
- 私有的静态变量,受到类域和访问限定符,更好体现封装,鄙人不能轻易修改,
- 提供一个共有的成员函数,利用匿名对象去调用;公有访问,类名::对象;
- 修饰全局变量或函数,改变的是链接接属性,旨在当前文件可见;
- 定义全局变量,明确调用了多少个构造对象。
输入输出操作符及重载、友元函数及类
- 友元函数
- 放在类里面的任何地方
- 还可以定义友元类,单向的,A是B的友元类,B不能访问A,A可以B
- 为了让cout在第一个参数,左左操作数,我们就只能写成全局的
- 其次就是operator<<搞成友元,可以在类中访问私有。
- 但是operator<<不是必须友元,还有其他方式
- 能不使用就不使用,破坏了封装
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "/" << d._month << "/" << d._day << endl;
return out;
}
istream& operator>>(istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
内部类
- 在类的里面定义另外一个类,计算大小不考虑内部类
- 受到A的类域的限制和访问限定符的限制,天生友元
- 还可以访问外类的静态
New、Delete、内存布局
- New是对operator new和构造函数的封装,是向系统申请,new[]申请的是连续空间,同时会执行N次构造函数,new在申请空间失败时会抛异常,new()是初始化
try
{
char* p2 = new char[0x7fffffff]; / 出错,抛异常,调到捕获异常的位置
}
catch (const exception& e)
{
cout << e.what() << endl;
}
- delete是对operator delete和析构函数的封装,delete[] 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理,下od同理
- operator new/ operator delete是两个全局函数,可实现向内存池申请和释放,提高效率
- placement-new :在已分配的原始内存空间中调用构造函数初始化一个对象
在堆上申请4G的内存
建议改为x64位
#include
using namespace std;
int main()
{
void* p = new char[0xfffffffful];
cout << "new:" << p << endl;
return 0;
}
内存泄漏的危害和防止
跑题是不存在的