C++|指针1

指针与指针变量

指针: 一个变量的地址
指针变量: 专门存放变量地址的变量

访问一个变量

①直接:通过变量名访问
②间接:通过指针变量访问

指针变量与指针的区别

指针变量

声明

static int i;
static int*ptr=&i;//int为指向的对象i类型
int *p1,p2;//p1为指针,p2为变量(对每个指针变量名,都需要一个*)

引用

i=3;
*ptr=3;//*ptr表示指向的那个值

赋值

  • 空指针:=NULL
int *p=NULL;//不指向任何对象
*p=8;

①当不知道指向哪里时/为了安全使用
②指向内存位置0的指针

  • 空类型指针:void *
char *p1;
void *p2;
p1=(char *)p2;//使用时需要强制转成被赋值类型
p2=(char *)p1;

①当不知道指向哪一种类型时
②使用时需要强制转成被赋值类型

初始化:指针名=地址

  • 两不要:
    不要使用未初始化的指针变量
    不要用内部auto变量初始化static指针

  • 可以初始化给:
    NULL
    已经定义的地址&x或指针*p
    动态分配内存

int *ptr3=NULL;
int x=31;//已经定义好的地址
//
int *ptr1=&x;//type*name=initialization(定义好的地址)
等价于👇
int *ptr;//声明一个指针
ptr=&x;//指针名=地址(向指针变量赋值,必须是地址常量或变量,为0时,表空指针)
//
ptr=0;//指针变量=0,表空指针

指针类型

它所指向变量的类型,而非本身数据类型
指针本身的数据值都是:unsigned long int

改变指针

可改:指向常量的指针

int a;
const int *p1=&a;//const说明p1指向常量,const不紧跟p1
int b;
p1=&b;//√ 可以改变指针变量,去指向不同的对象
*p1=1;//× 不能改变指针指向的值,因为const

不可改:指针变量为常量

int a;
int *const p2=&a;//p2指针为const类型,不可改
p2=&b;//× 不能改变访问的对象(p2值不能变)
int *const ptr=&a;//const紧跟ptr
*ptr=7;//√,*ptr is not const(地址不变,指向的可以变)
ptr=&y;//× ptr is const,不能改访问对象(ptr地址不变)
int x=5;
const int *const ptr=&x;//ptr and *ptr are both const
*ptr=7;//× *ptr is const
ptr=&y;//× ptr is const

指针运算

与整数
实质:地址运算
加:下一个
减:上一个

*(pa-n)=pa[-n];//移到前n个数据
*(pa+n)=pa[n];//移到后n个数据
  • short*pa:每个变量占两个位置,pa[n]两个两个的移
  • long *pa:每个变量占四个位置,pa[n]四个四个的移

指针之间(同类型的指针变量)

  • p1-p2:
  • 结果为各自指向对象之间间隔的数据个数(为整数)
    
//计算数组元素个数
p1=&a[0];
p2=&a[];
p1-p2;//

关系运算(同类型指针)

p==NULL;
p!=NULL;

指针处理数组

声明与赋值

int a[10],*pa;//声明数组与指针
pa=&a[0];//指针变量=数组取首地址(本身指针变量就是地址)
或
pa=a;//指针名=数组名

引用

*pa即a[0]
*(pa+n)即a[n]
a[i]*(pa+i)*(a+i)即pa[i]//∵pa=a,a为数组首地址,pa也为一个地址

指针数组

是个数组,数组元素是指针
指针数组指向几个二维数组时:

int* pline[3] = { line1,line2,line3 };//定义指针数组并初始化为整型数组,三个元素
for (int i = 0; i < 3; i++)//第一行
{
 for (int j = 0; j < 3; j++)//第一列
	cout << pline[i][j] << " ";//注意前面* pline[3],此处相当于pline等于line123构成的数组,故变成了二维数组

在这里插入图片描述

指针作为函数参数

形参是指针时实参可以为数组 (指向普通变量)

void print(const int* p1, const int *p2);
……
print(array1,array2 );
print(&array[i],&array[i+1]);//若为数组中某个值时,带上&

形参是指向类对象的指针

void fun(Base1* ptr) {//一个函数,形参是指向->基类base1的对象的 指针*ptr
	ptr->display();//调用类中成员函数:对象指针->成员名 
}

形参是指针时
交换两个指针:

  • 指针指向的对象交换了
  • 指针变量没有交换

指针大小

  • 任何类型的指针变量都是占用4个字节。
    (指针即为地址,指针几个字节跟语言无关,而是跟系统的寻址能力有关,譬如以前是16为地址,指针即为2个字节,现在一般是32位系统,所以是4个字节,以后64位,则就为8个字节)
  • 指针占用多少字节=数据类型占用多少字节
int main() {
	double array[20];//声明数组,20个元素
	cout << "The number of bytes in the array is" << sizeof(array);//20*8=160
	cout << "\nThe number of bytes returned by getsize *ptr&ptr is";
	getsize(array);//形参为指针,实参可以是数组
}
void getsize(double* ptr) {//传入的时指针*ptr
	cout << sizeof(*ptr) <<" "// 返回指针*ptr指向的double型数据,double是8位
		<< sizeof(ptr) << endl;//返回的是指针变量的大小,任何类型的指针变量都是4(32位系统时)
}

注意*ptr与ptr的占位大小不同

函数指针与指针函数

函数指针:
函数指针本质是一个指针,其指向一个函数(会用上此函数)

指针函数:
指针函数本质是一个函数,其返回值为指针

对比:

  • 指针函数:int* fun(int x,int y);
    函数指针:int (*fun)(int x,int y);
  • 可以简单粗暴的理解为,指针函数的*是属于数据类型的,而函数指针的星号是属于函数名的。
    再简单一点,可以这样辨别两者:函数名带括号的就是函数指针,否则就是指针函数。
  • 声明
int (*fun)(int x,int y);//类型说明符 (*函数名) (参数)

//指向的是类非静态成员函数,非静态,不在全局作用
int(point:: * funcptr)()//定义成员函数指针//typedef 返回值 (类名::*指针类型名)(参数列表);
const = &point::getx;
  • 赋值
fun = &Function;//赋值,将函数地址赋给指针变量,使函数指针指向fun函数,从而与fun功能相同
fun = Function;//&可有可无

//指向的是类非静态成员函数
const = &point::getx;//定义成员函数指针;指针类型名  指针名 = &类名::成员函数名;
  • 调用
//直接调用函数
(*fun)();//通过指针的方式来调用函数,注意两个括号
fun();

//类对象调用函数
(a.*funcptr)();//对象名.指针访问成员函数
a.getx();//对象.成员函数名

谁是指针就写成指针形式
(p1->*funcptr)() ;//对象指针名->成员函数指针
p1->getx();//对象指针名->成员函数(类对象.*指针名)(参数列表);
(类指针->*指针名)(参数列表);

那么类的静态成员函数呢?
指向的是类静态成员函数,静态,在全局作用,视为普通函数,则用法相同

用指针访问

访问类静态数据成员

int* ptr = &point::count;//指针创建,指向类的静态成员,类的静态成员使用时要类名::
	point a(4, 5);
	cout << "object count=" << *ptr << endl;//使用指针访问静态数据成员
	cout<< "object count=" << point::count << endl;//与上等价

杂代码

int main() {
	derived d;//子类对象
	derived* p = &d;//子类 指向对象d的指针

	d.var = 1;//子类对象访问同名成员,默认本类成员
	d.fun();

	d.base1::var = 2;//子类对象要访问父类成员,父类::修饰
	d.base1::fun();

	p->base2::var = 3;//子类对象指针访问父类成员
	p->base2::fun();

	return 0;

类后引用??不太懂 return*this作对应

clock& clock::operator++() {//前置重载
		second++;
		if (second >= 60) {
			second -= 60;
			minute++;
			if (minute >= 60) {
				minute -= 60;
				hour = (hour + 1) % 24;//!24进制进位方法!
			}
		}
		return *this;//与&clock匹配,返回clock类型
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值