一些容易混淆的概念

1.delete 和 delete[]

前提了解

  • 系统默认实现了 new/delete、new[]/delete[]、placement new/delete(借助已经存在的内存来构建对象)6个运算符函数
  • new 完成两个工作:1.分配一块动态内存空间;2.调用构造函数初始化对象
  • delete 完成两个工作:1.调用对象类型的析构函数;2. 释放这块内存空间
  • C++ 中分配数组内存时系统内部会增加4/8子节的分配空间来保存所分配的数组对象的数量;当对数组对象调用构造和析构函数时就可以根据这个数量值对每个数组元素进行遍历处理了;此外,只会对类类型增加额外内存保存数量而基础类型不会(基础的没有析构函数)
  • 支持new/delete 运算符的重载:
  • new 关键字创建堆内对象有两部,任何一步都会异常:
    • 如果在第一步出现了问题导致内存分配失败则不会调用构造函数,这是没有问题的
    • 如果在第二部构造函数执行过程中出现了异常就会停止构造函数的执行并且自动调用对应的delete运算符来对已经分配的堆内存进行执行销毁处理,此为对象的自动删除计数
  • 全局delete 运算符函数所支持的对象自动删除计数虽然能解决对象本身的内存泄漏文图,但不能 解决对相关构造函数内部的数据成员的内存分配泄漏问题, 所以可以重载delete运算符
  • 使用new 申请的单个对象的内存空间的释放,需要使用delete
  • 使用new[] 申请的一组对象的内存空间的释放,可以分为两种:
    • 基本数据类型:如int* a = new int[10]; 此时使用delete或delete[]都能释放,基本类型对象没有析构函数,且在内存分配时会记录分配的空间大小,所以delete能正确释放内存
    • 类类型:如 Student* p = new Student[10]; 如果是delete p,则只会调用p[0]这个元素的析构函数,剩余的元素内存没有被释放;上面说了对类类型的数组会有额外的空间来存放数据数量,调用delete[] 会对数组元素逐一调用析构函数
  • 总言之,配对使用

接下来两个,辨别的方式是从右往左读,就近原则

2.常量指针和指针常量

  • 常量指针: 首先是指针,指向一个常量;const *
    • 不能通过该指针改变所指对象的值,但没有规定那个对象的值不能通过其他途径改变:指向常量的指针,只是这个指针自己觉得既然指向了常量,自己觉得不应该改变那个值
    • 一般指针类型和所指类型要保持一致,这里允许一个指向常量的指针指向一个非常量对象
  • 指针常量: 首先是常量,类型是指针类型;* const
    • int* const cp;//从右向左,离cp 最近的是const,所以 cp 本身是常量,对象类型右声明符的其余部分确定,下一个符号是*,所以p是常量指针,最后一个是int ,连起来就是常量类型的整型指针
    • 既然是常量,那么指针指向的地址不可以变,但地址的内容可以变
  • 顶层const:表示指针本身是一个常量;底层 const:表示指针所指的对象是一个常量

3.数组指针和指针数组

  • 数组指针: 首先是指针,指向一个数组——指向数组首地址的指针

    • float a[4][5]; float (*p)[5] = a;
      从右向左看,但括号优先级高,所以先确定p是一个指针,再看[],这个指针指向的对象是一个数组,最后是float,连起来,p是一个指向包含4个float类型一维数组的指针
      void test_08() {
      	int num = 0;
      	int a[4][5];
      	int(*p)[5] = a;//
      	for (int i = 0; i < 4; i++) {
      		for (int j = 0; j < 5; j++) {
      			*(*(p + i) + j) = num++;
      		}
      	}
      	//range for 只能遍历
      	for (auto &i : a) {
      		for (auto j : i) {
      			cout << j << "\t";
      		}
      		cout << endl;
      	}
      }
      
  • 指针数组: 首先是数组,数组的元素是指针

    • float * p [5];
      从右向左看,首先是[],确定p是一个数组,再看到*,确定数组的元素是指针,最后float,连起来,p是一个包含5个float指针的数组
  • **优先级:()> [] > * **


4.初始化和赋值

  • 初始化不是赋值
  • 初始化的含义是创建变量时赋予一个初始值
    • 拷贝初始化: 使用 = ,将等号右侧的初始值拷贝到新创建的对象中【类存在拷贝构造函数】
    • 直接初始化: 不适用 = ,小括号,花括号
  • 赋值的含义是**把已有的对象的值擦除,**以一个新的值代替【类中赋值运算符重载】
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

明前大奏

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

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

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

打赏作者

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

抵扣说明:

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

余额充值