概述
指针
指针声明: int * p_updates = &变量;
(变量类型和指针类型相同) -----表明* p_updates
的类型是 int
。 p_updates
是指针 (地址);*p_updates
是int
,不是指针;
在声明语句中初始化指针时,初始化的是指针(地址),不是指针指向的值。
××××××××一定要在对指针应用解除引用运算符*
前,将指针初始化为一个确定的,适当的地址;
指针类型也可以是结构,函数等
空指针:
1,空指针用于给指针变量初始化 : int * p = NULL
;
2, 空指针是不可以进行访问的; 如 *p=100
;会报错;
野指针:即指针变量指向非法的内存空间: int * p = (int *)0x1100;
没有权限去访问该地址,因为我们没有申请该地址;如果使用*p
就会报错;
const
修饰指针:
—常量指针 const int * p = &a;
等价于 int const *p = &a;
常量指针的特点: 指针指向可以修改: p = &b;
但是指向的值不可以改: *p = 2000;
int a = 10;
const int *p = &a;
int b = 20;
//*p = 2000;//报错
p = &b;
—指针常量 : int * const p = &a;
指针常量的特点: 指针指向不可以改: p = &b
,但是指针指向的值可以改: *p = 2000;
int a = 10;
int *const p = &a;
int b = 20;
*p = 2000;
//p = &b;//报错
—即修饰指针,又修饰常量 int const *const p = &a;
int a = 10;
const int *const p = &a;
int b = 20;
//*p = 2000;//报错
//p = &b;//报错
其他情况:
1, int *p
指针指向 const int a
常量的情况
//example
const int a = 10;
int * p;
//p = &a; 会报错,不能将 "const int *" 类型的值分配到 "int *" 类型的实体
//p = (int *)&a;
p = (int *)&a;//可以通过,但是依旧不能通过*p修改a的取值
*p = 100;
cout << a << endl;//10
cout <<*p<<endl;//100
2,const int *p
指针指向 const int a
常量的情况
//example
const int a = 10;
const int * p;
p = &a;
//但同样无法通过*p修改a的值
指针和数组:
目的:利用指针访问数组的元素;
重点一句话:数组名是一个指针常量
//example
int array[6] = {1,2,3,4,5,6};
int *p = array;//此时*p指向第一个元素(索引0);
p++;//指针后移4个字节,指向第二个元素地址(索引1);
*(p+2);//指针不移动, 此时*(p+2)指向第四个元素(索引3),p依旧指向第二个元素的地址(索引1);
指针和函数:
1,值传递----即函数输入为数据副本;
—函数声明时:functionname(int a,int b);
—函数调用时: functionname(a,b);
2,地址传递—即函数输入为地址;
—函数声明时:functionname(int *p1,int *p2);
—函数调用时: functionname(&a,&b);
3,引用传递—即函数输入为数据本身;
—函数声明时:functionname(int &a,int &b);
—函数调用时: functionname(a,b);
函数指针声明:
double pam(int); //------先声明函数pam
double (*pf)(int);
pf = pam;//-------就是 pam 换成(*pf)
//pf = &pam // 这样也是可以的
当把函数地址传递给一个函数时,该函数可以在内部使用该地址下的函数;
void estimate(int a, double (*pf)(int)) //----函数声明;
estimate(2,pam); //----函数调用在函数estimate内部,可以使用(*pf)调用每次传入的对于实参函数;
//example
int add(int arr[][3],int size)
{
int total = 0;;
for(int i = 0; i < size; i++)
{
total += arr[i][0];
total += arr[i][1];
total += arr[i][2];
}
return total;
}
void print(int arr[][3], int size, int (*pf)(int[][3],int) )
{
cout << (*pf)(arr,3) << endl;
}
int main()
{
int arr[3][3] = {{1,1,1},{2,2,2},{3,3,3}};
int (*pf)(int[][3],int);
pf = add; // pf = &add //任意一种都一样
int total = (*pf)(arr,3); //int total = pf(arr,3) //任意一种都一样
cout<< total << endl;//18
print(arr,3,pf);//18
}
func
和 *funp
在使用时可以相互替换,但是在函数声明时,只能用func
, 在函数指针声明时只能用*funp
void MyFun(int); //*不能写成 void (*MyFun)(int)。*/
void (*FunP)(int); //*不能写成 void FunP(int)。*/
使用new来分配内存:
typename *pn = &变量;
typeName * point_name = new typeName;
----只能通过pn
访问地址;前一种可使用&变量
访问;
当使用new声明指针后,使用完,一定要使用delete删除—这将删除指针所指向的内存,但不会删除指针本身。 —一定要配对使用new 和delete
int *a = new int;
//int* a = new int(10);//推荐这样
//int b =10; a = &b; //不能这样使用,若这样使用,delete a;会出错,delete 会删除a指向的地址,也就是b的地址;
*a = 10;
cout<< a<<endl;
delete a;
a = new int; //删除后,可以重新分配内存;注意delete a 后,a还是存在的,所以不能 int* a = new int;
使用new 来创建动态数组
typeName * pointer_Name = new typeName [size];
----new
将返回第一个元素的地址;将该地址赋值给pointer_Name
;
对于new 创建的动态数组,使用delete来释放— delete [] arrayName;
//example
int *arr = new int[3]{0,0,0};
//int *arr = new int[3];
cout << arr[2] <<endl;
*(arr+2) = 10;
cout << arr[2] <<endl;//10
delete [] arr;
使用new 创建动态struct
structionname * name = new structionname;
成员调用使用->
来调用–地址调用; ------当变量的类型是结构体时,使用句点运算符,当变量的类型是结构(类)的指针时,使用箭头运算符;或者(*name)使用句点运算符调用成员;
struct Stu{
string name;
int age;
Stu(){}
Stu(string s, int a):name(s),age(a){}
};
Stu *student = new Stu;
student->age = 10;
(*student).name = "wang";
cout << (*student).age << endl;
cout << student->name << endl;
delete student;
//Stu *student_1 = new Stu("li",20);//这里不能使用student,delete 释放了指向的内存,但是该变量依旧存在。
student = new Stu("li",20);
cout << (*student).age << endl;
cout << student->name << endl;
指针的指针 **
int a = 10;
cout << "address of a = " <<&a << endl;
int * p = &a;
cout << "address of p = " <<&p << endl;
int ** pf = &p;
cout<< pf << endl;//p的地址
cout << *pf << endl;//a的地址
cout << **pf << endl;//10
内存 | 地址1 | 地址2 | 地址3 | 地址4 |
---|---|---|---|---|
变量值 | 10 | 地址1 | 地址2 | |
变量名 | a | p | pf |
int a = 10;//申请内存1,命名为a,放入变量值10;
int *p ; //申请内存2,命名为p,变量值初始;
p = &a; //p的变量值等于a的地址(1);
int ** pf;//申请内存3,命名为pf,变量值初始;
pf =&p;//将pf中的变量值改变为p的地址(2);
*pf;//*pf是pf中变量值的变量值,即地址1
**pf;//*p是a的地址,**p自然是a的值
应用实例
设计一个函数:void find(int array[],int size, int search, int **ppa)
要求:要求在array 中查找参数 search 。如果找到,函数通过第三个参数返回值为 array 中第一个找到的serach的地址。如果没找到,则第三个参数为 0。
void find(int array[],int size, int search, int **ppa)
{
int i;
for (i=0; i< size; i++)
{
if(array[i] == search)
{
*ppa = array + i;
return;
}
}
*ppa = 0;
}
//主函数的调用:
int arr[4] ={1,2,3,4};
int * pf;
find(arr,4,3,&pf);
cout<<pf<<endl;
cout<<&arr[2]<<endl;//两次打印值相同;
在这个例子中第三个参数就要使用** ,若使用* ,则无法完成任务,如下:
void find(int array[],int size, int search, int *ppa)
{
int i;
for (i=0; i< size; i++)
{
if(array[i] == search)
{
//*ppa = array + i;//这里就会报错,因为*ppa的类型是int
ppa = array + i;//这样虽然可以赋值,但是将ppa中的值改变为了array + i;则对外界传入的实参地址进行了覆盖。则相当于只是修改了形参,不能改变实参
return;
}
}
*ppa = 0;
}
//主函数的调用:
int arr[4] ={1,2,3,4};
int * pf;
cout<<pf<<endl;//0
find(arr,4,3,pf);
cout<<pf<<endl;//0,表示没有找到;若里面找到了,就会被覆盖,不能修改pf的值,则pf还是初始值0;若里面找不到,就会赋值为0;故,找不找得到都是0;
cout<<&arr[2]<<endl;
最后
以上就是平淡可乐为你收集整理的c++知识点总结 -- 指针的全部内容,希望文章能够帮你解决c++知识点总结 -- 指针所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复