c++知识点总结 -- 指针

指针

指针声明: int * p_updates = &变量;(变量类型和指针类型相同) -----表明* p_updates的类型是 intp_updates 是指针 (地址);*p_updatesint,不是指针;
在声明语句中初始化指针时,初始化的是指针(地址),不是指针指向的值。
××××××××一定要在对指针应用解除引用运算符*前,将指针初始化为一个确定的,适当的地址;
指针类型也可以是结构,函数等
空指针:
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
变量名appf

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;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值