野指针及c++指针使⽤注意点
避免野指针的产⽣
“野指针”的成因主要有:
1)指针变量没有被初始化。任何指针变量刚被创建时不会⾃动成为NULL指针,它的缺省值是随机的,它会乱指⼀⽓。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
char *p; //此时p为野指针
2)指针p被free或者delete之后,没有置为NULL,让⼈误以为p是个合法的指针.
char *p=new char[10];  //指向堆中分配的内存⾸地址,p存储在栈区
cin>> p;
delete []p; //p重新变为野指针
3)指针操作超越了变量的作⽤范围。
char *p=new char[10]; //指向堆中分配的内存⾸地址
cin>> p;
cout<<*(p+10); //可能输出未知数据
指针的注意点:
a.指针指向常量存储区对象
char *p="abc";
此时p指向的是⼀个字符串常量,不能对*p的内容进⾏写操作,如srtcpy(p,s)是错误的,因为p的内容为“abc”字符串常量,该数据存储在常量存储区,但可以对指针p进⾏操作,让其指向其他的内存空间。
b.资源泄漏
问题:
1 #include<iostream>
2using namespace std;
3void main()
4 {
5char *p=new char[3];  //分配三个字符空间,p指向该内存空间
6    p="ab";            //此时p指向常量“ab”,⽽不再是new char分配的内存空间了,从⽽造成了资源泄漏
7delete []p;        //释放时报错
8 }
结果:卡死
改进:
1 #include<iostream>
2using namespace std;
3void main()
4 {
5char *p=new char[3];  //分配三个字符空间,p指向该内存空间
6    strcpy(p,"ab");      //将"ab"存储到p指向的内存空间
7delete []p;        //ok
8 }
结果:正确
c.内存越界
1char *p=new char[3];  //分配三个字符空间,p指向该内存空间
2 strcpy(p,"abcd");    //将abcd存处在分配的内存空间中,由于strlen("abcd")=4>3,越界
3delete []p;        //ok
d.返回值是指针
问题:数组p[]中的内容为“hello world”,存储在栈区,函数结束时内容被清除,p变为野指针,可能导致乱码 1 #include<iostream>
2using namespace std;
3char *f()
4 {
5char p[]="abc";
6return p;
7 }
8void main()
9 {
10    cout<<f()<<endl;
11 }
结果:
改进:
1.加static限定,延长数组⽣存期
1 #include<iostream>
2using namespace std;
3char *f()
4 {
5static char p[]="abc";  //此时数组为静态数组,存储在全局/静态区,⽣存期到程序结束,因此函数结束时不会销毁p
6return p;
7 }
8void main()
9 {
10    cout<<f()<<endl;
11 }
结果:
2.定义成指针型数组
1 #include<iostream>
2using namespace std;
3char *f()
4 {
5char *p="abc";    //"abc"存储在⽂字常量区,p是指向常量的指针,⽣存期到程序结束
6return p;
7 }
8void main()
9 {
10    cout<<f()<<endl;
11 }
结果:
3.动态分配存储空间,存储在堆区
1 #include<iostream>
2using namespace std;
3char *f()
4 {
5char *p=new char[5];  //动态分配存储空间,p指向堆区
6    strcpy(p,"abc");  // 这⾥不能⽤p="abc",前⾯已经说明
7return p;
8 }
9void main()
10 {
11    cout<<f()<<endl;
12 }
结果:
e.指针做形参
即所谓的地址传递,我们都知道地址传递的⽅式,形参的改变会导致实参的改变,但要注意的是,这⾥的改变是指指针所指内容的改变,⽽不是指针值的改变。因此,当形参改变会导致实参改变时,指针所指的内容是⾮const类型的,否则会出错。
1.改变指针内容:
1void swap(int *a,int *b)  //交换的是*a,*b,即指针的内容,⽽不是指针a,b
2 {
3int t;
4    t=*a;
5    *a=*b;
6    *b=t;
7 }
2.改变指针值:
1 #include<iostream>
2using namespace std;
3void fun(char *p)
4 {
5    p="cba";    //“cba”存放在⽂字常量区,让p指向常量"abc",这⾥改变的是指针值,实参并不会改变
6 }字符串常量区放在哪
7void main()
8 {
9char *p="abc";  //“abc”存放在⽂字常量区,p指向常量"abc"
10    fun(p);
11    cout<<p<<endl;  //输出"abc",⽽不是"bca"
12 }
结果:
继续看下⾯的情况,修改指针的内容:
1 #include<iostream>
2using namespace std;
3void fun(char *p)
4 {
5    p[0]='c';    //改变p的内容,即修改p[0]
6 }
7void main()
8 {
9char *p="abc";  //p指向常量"abc"
10    fun(p);
11    cout<<p<<endl;  //error,p所指内容为常量,不能修改
12 }
结果:
注:p="ab"和strcpy(p,"ab"),含义不⼀样,前者指针p指向常量“ab”存储区域的⾸地址,改变了p最开始指向的new申请的内存空间;⽽后者是将“ab”分配到new申请的内存空间中;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。