Boolan C++第二周笔记

编写一个带指针成员变量的类

1. 拷贝函数

  • 当类中有指针成员变量时,必须要实现拷贝函数,不能使用系统提供的默认方法。

2. Big Three

  • 拷贝构造
  • 拷贝赋值
  • 析构函数

字符串的两种存储形式:最前存贮字符串的长度;最后有结束符'\0'

2.1 拷贝构造函数

  • 构造函数的参数类型为本class
  • new一份同样大小的内存,再使用strcpy

大小要+1,为结束位的'\0'留出位置

2.1 拷贝赋值函数

  • 重载运算符=
  • 监测是否自我赋值。之后先清空,在申请同样大小的内存,再拷贝strcopy

如果没有做自我赋值检测,会出现把自己清空后再赋值,这时调用指针会出现不确定结果

3. 堆栈

  • 堆,heap。由操作系统提供的一块global内存空间,程序可动态分配。通过 new去获得。malloc
    • 局部的指针变量如果没有被delete,那么指针变量的堆空间将无法被安全释放,造成了内存泄漏。
    • new的流程:先分配memory,再调用构造函数。
void* mem = operator new( sizeof(Complex) ); //分配内存,调用malloc(sizeof()) 
pc = static_cast(mem);             //类型转换
pc->Complex::Complex(1,2);                   //构造函数
  • 堆,heap
    • delete的流程:先调用析构函数,再释放memory
String::~String(ps);   //析构函数
operator delete(ps);   //释放内存,内部调用free
  • 栈,stack。存在于作用域内的一块内存空间。
    • 局部对象,会被自动清理。
    • static关键字。静态对象的生命周期和程序绑定,和作用域无关。
    • 全局对象。

4. 内存中new时的真正形态

4.1 单个对象时

  • debug模式
    • 每申请一个对象,内存中的实际大小为:
      • 对象本身的内存大小
      • 包裹对象的内存32字节+4字节
      • cookie内存4+4,在整个内存块的头和尾
      • 全部大小相加后,再向16的倍数对齐
  • release模式
    • 每申请一个对象,内存中的实际大小为:
      • 对象本身的内存大小
      • cookie内存4+4,在整个内存块的头和尾
      • 全部大小相加后,再向16的倍数对齐
  • cookie内存的作用
    • 标记回收时的内存大小
    • 因为一定是16的倍数,所以最后一位一定是0,可以利用最后一位的0/1来标示当前内存块是给出状态还是回收状态

4.2 数组对象时

  • new type[] 要搭配 delete []
  • debug模式
    • 每申请一个对象,内存中的实际大小为:
      • 记录数组大小:4字节
      • 数组长度个的对象本身的内存大小:n * object
      • 包裹整个数组和大小的内存32字节+4字节
      • cookie内存4+4,在整个内存块的头和尾
      • 全部大小相加后,再向16的倍数对齐
  • release模式
    • 每申请一个对象,内存中的实际大小为:
      • 记录数组大小:4字节
      • 数组长度个的对象本身的内存大小:n * object
      • cookie内存4+4,在整个内存块的头和尾
      • 全部大小相加后,再向16的倍数对齐

5. 类模版

template
class complex
{
public:
  complex (T r = 0, T i = 0)
    : re (r), im (i)
  {}
private:
  T re, im;
}

6. 函数模版

template 
inline 
const T& min(const T& a, const T& b)
{
  return b < a ? b : a;
}

思考

1. new type[] 和 delete [] 成对出现的原因?

  • 如果不成对出现,会造成内存泄漏,但是泄漏的内存并不是数组中对象的内存,数组中的所有对象已经被正确释放。delete[]的作用是,通知编译器释放的是个数组对象,然后调用多次的析构函数;如果只是调用delete,只会调用一次析构函数。
  • 所以真正内存泄漏的内存,是数组对象中指针所指向的那些内存。也就是说如果当数组对象的内部变量没有指针时,是不会出现问题。
  • 要保持良好的变成习惯,array new 和 array delete要成对出现。

2. ' * '和' & '标志符在不同位置时的不同含义

  • ' & '在类型名后' typename& ',表示为引用;' & '在对象前' &object ',表示为取地址

3. 回答第一周笔记中的第一个思考问题,为什么可以数据需要单独存储,而函数可以公用一份?

  • 通过对象调用类方法时的真相
complex c1,c2;
cout << c1.real(); // 实际情况,cout << complex::real(&c1);
cout << c2.real(); // 实际情况,cout << complex::real(&c2);

4. 为什么静态函数只能使用静态数据,而不能使用直接使用类的私有数据?

  • 因为static函数的参数列表中,没有默认的this指针。
  • 静态函数可以通过类名调用,也可以使用对象调用。

5. 类模版和函数模版的使用区别

  • 类模版使用时必须明确指出模版的类型;函数模版使用时,不用明确指出,编译器会进行argument deduction,参数推导

你可能感兴趣的:(Boolan C++第二周笔记)