C++指针

## 野指针
概念
野指针就是指向一个已删除对象或者未申请访问受限内存区域的指针
产生原因
1.指针定义时未被初始化:指针在被定义的时候,如果程序不对其初始化的话,它会随机指向一个区域,因为任意指针数量(除了static修饰的指针)它的默认值都是随机的。
2.指针被释放时没有置空:我们在用malloc()开辟空间的时候,要检查返回值是否没空,如果为空,则开辟失败。指针指向的内存空间在用free()和delete释放后,如果程序员没有对其进行置空或者其他赋值操作的话,就会成为一个野指针。
3.指针操作超越变量作用域:不要返回指向栈内存的指针或者引用,因为栈内存在函数结束的时候会被释放
危害
指针指向的内容已经无效,而指针没有被置空,解引用一个非空的无效指针是一个未被定义的行为,也就是说不一定导致错误,野指针被定位到哪里出现问题,在哪里指针就失效了,不好查找错误原因
规避方法
初始化指针的时候将其置为nullptr,之后对其操作,释放指针的时候将其置为nullptr
空指针,野指针和悬空指针的区别
空指针:被赋值为NULL的指针,空指针可以多次被delete
野指针:访问一个已销毁或者访问受限的内存区域的指针,野指针不能判断是否为NULL来避免
悬空指针:若指针指向一块内存空间,当这块内存空间被释放后,该指针依然指向这块内存空间,此时,称该指针为悬空指针,悬垂指针再次删除时程序会变得非常不稳定

函数指针
定义:函数指针时指向函数的指针变量,该指针变量指向一个具体的函数,这正如指针变量可指向整型变量,字符型,数组一样,这里是指向函数。C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同指针变量可引用其他类型变量一样,这些概念是大体一致的。
用途:调用函数和做函数的参数,比如回调函数

char *fun(char *p){} //函数fun
char* (*pf)(char * p); //函数指针pf
pf = fun;            //函数指针pf指向函数fun
pf(p);               //通过函数指针pf调用函数fun

this指针
概念:指向类的当前对象的指针常量
1.this指针是一个隐含于每一个非静态成员常量的特殊指针,它指向调用该成员函数的那个对象
2.当对一个对象调用成员函数时,编译程序先将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员时,都隐式使用this指针
3.当一个成员函数被调用时,自动向它传递一个隐含的参数,该参数是一个指向这个成员函数所在的对象的指针
4.this指针被隐含的声明为ClassName const this,这意味着不能给this指针赋值,在ClassName类的const成员函数中,this指针的类型为const ClassNameconst,这说明不能对this指针所指向的对象的数据成员进行赋值操作
5.this并不是一个常规变量,而是个右值,所以不能取得this的地址(不能&this)
6.在以下场景中,经常需要显式引用this指针
为实现对象的链式调用
为避免对同一对象进行赋值操作
在实现一些数据结构如list时

this指针什么时候创建的
this在成员函数的开始执行前构造,在成员的执行结束后清除

如果class或者struct里面没有方法的话,它们是没有构造函数的,只能当做C的struct使用。采用TYPE xx的方式定义的话,在栈里分配内存,这时候this指针的值就是这块内存的地址。采用new的方式创建对象的话,在堆里分配内存,new操作符通过eax(累加寄存器)返回分配的地址,然后设置给指针变量。之后去调用构造函数(如果有构造函数的话),这时将这个内存块的地址传给ecx,之后构造函数里面进行处理

this指针存放在何处?堆,栈,全局变量还是其他
this指针会因编译器不同而有不同的放置位置,可能是栈,也可能时寄存器,甚至是全局变量,在汇编级别里面,一个值只会以三种形式出现:立即数,寄存器值,和内存变量值。不是存放在寄存器就是存放在内存中,他们并不是和高级语言的变量所对应的

每个类编译后,是否创建一个类中函数表保存函数指针,以便用来调用函数?
普通的类函数(不论是成员函数,还是静态函数)都不会创建一个函数表来保存函数指针。只有虚函数才会被放到函数表中。但是,即使是虚函数,如果编译期就能明确知道调用的是哪个函数,编译器就不会通过函数表中的指针来间接调用,而是会直接调用该函数。正是由于this指针的存在,用来指向不同的对象,从而确保不同对象之间调用相同的函数可以互不干扰

delete this合法么
合法,但:
1.必须保证this对象是通过new分配的
2.必须保证调用delete this的成员函数是最后一个调用this的成员函数
3.必须保证成员函数的delete this后面没有调用this了
4.必须保证delete this后没人使用了

指针和引用的区别
1.指针有自己的一块空间,而引用就只是一个别名
2.使用sizeof看一个指针的大小是4,而引用则是被引用对象的大小
3.指针可以被初始化为NULL,而引用必须被初始化且必须是一个已有对象的引用
4.作为参数传参时,指针需要被解引用才可以对对象进行操作,而直接引用的修改都会改变引用所指向的对象
5.可以有const指针,但是没有const引用
6.指针在使用过程中可以指向其他对象,但是引用只能是一个对象的引用,不能被改变
7.指针可以有多级指针,而引用只有一级
8.指针和引用使用++有运算符的意义不一样
9.如果返回动态内存分配的对象或者内存,必须使用指针,引用可能会造成内存泄露

C++中指针与引用可以只要一个么
为什么有了引用还需要指针呢
答:因为为了兼容C语言,必然要支持指针
为什么有了指针还需要引用呢
答:一开始C++是没有引用的,比如说:this被定义为了指针而不是引用,后来加入引用的原因主要是为了支持运算符重载。假设C++里面没有引用,而只有指针,会有什么样的问题。如果用指针来运算符重载的话,就像

ClassFun operator+(const ClassFun *,const ClassFun *)

使用的时候只能是&a+&b,这和我们通常的写法a+b不太一样,看上去不太习惯。还可以进一步假设,也就是可以写成a+b,让编译器来根据operator+的类型来解释a和b的类型。如果operator+的参数是值,那就解释成值,如果是指针,那就解释称地址。这和现在C++里面把名字解释成值或引用是一个道理。这样做的后果是值和指针不能重载了

引用带来的好处:用指针的使用经常犯的错:1.操作空指针2.操作野指针3.误操作改变了指针的值,而后还以为指针正常,引用区别于指针的特征是:1,不存在空引用(保证不操作空指针)2.必须初始化(保证不是野指针)3.一个引用永远指向它初始化的那个对象,一旦初始化就不能改变初始化的值(保证指针的值不变),人为保证变为了编译器来保证,更加安全

注意事项:
用户自定义的类型最好用引用传参,这样可以避免不必要的构造函数和析构函数的调用,但是像int,long,char一类的内置类型,按值传参会比按引用传参更高效

指针参数传递和引用参数传递的区别
1.指针参数传递的本质是值传递,它所传递的是一个地址值,值传递的过程中,被调函数的形式参数作为被调函数的局部变量处理,会在栈中开辟内存空间以存放由主调函数传递进来的实参的值,从而形成了实参的一个副本,值传递的特点是,被调函数对形式参数的任何操作都是作为局部变量进行的,不会影响主调函数的实参变量的值(形参指针变了,实参指针不会变)
2.引用参数传递过程中,被调函数的形式参数也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参(本体)的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量(根据别名找到主调函数中的本体)。因此,被调函数对形参的任何操作都会影响主调函数中的实参变量

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值