【C++中阶教程1】指针

为什么学习指针

  1. 阅读他人代码
  2. 与API沟通
  3. 有时候必须要使用指针

什么是指针

不幸的是,这个问题有一个非常简单的答案:
A pointer is just a variable that holds a memory address
在这里插入图片描述
有疑问请参考 link【C++中阶教程0】内存/二进制/变量


更不幸的是,如果你去问百度:

在这里插入图片描述
WTF…


其实指针的使用忌讳想得太多,越想越容易乱套;但如果想用好的话,必须刨根问底学习透彻,不要害怕,耐心读完本文便会拨云见日。


C++里,

* 为 声明指针间接引用 操作符

& 为 address of 操作符


再次强调:

A pointer is just a variable that holds a memory address

  1. 指针的本质,就是一个变量,它的声明格式也完全一致
  2. 指针变量hold的是指针类型,但是它需要知道自己指向的类型(单纯理解为兼容性即可)

int main()			术语版
{
	int n = 5;		声明1个变量,名字是n,编译器分配4个byte来存储它的值5,简称“初始化为5int* p;			声明1个特殊变量:指针,名字是p,编译器分配4个byte,没有初始化,指向随机位置
	p = &n;			&n = address of n,告诉p往哪儿指
	*p = *p + 64;	*p = 引用p指向的目标,也就是5,加上64得出神奇数字69
	
	return 0;
}
int main()			大白话版
{
	int n = 5;		楼里来了个新住户n
	int* p;			买了个小本儿,叫p
	p = &n;			小本儿上记下了n的门牌号
	*p = *p + 64;	查阅小本儿,找n家里去了
	
	return 0;
}

来看几种其它情况

int main()
{
	int n = 5;		
	int* p;			
	p = 4;			错误,不能将int赋给int pointer
	*p = *p + 64;
	
	return 0;
}
int main()
{
	int n = 5;
	float f = 6.9f;		
	int* p;			
	p = &f;			错误,不能将float pointer赋给int pointer
	*p = *p + 64;
	
	return 0;
}
int main()
{
	int n = 5;		
	int* p;			
	p = nullptr;	正确,nullptr很常用,为特殊值null pointer,表明这个指针现在毛都没指,
	*p = *p + 64;
	
	return 0;
}
int main()
{
	int n = 5;		
	int* p = &n;
	*p = *p + 64;
	int* q = p;		正确,类型兼容,现在q和p都指向n
	
	return 0;
}

三次强调: pointer也是变量,就同样需要分配对应类型对应大小的内存
int main()
{
	int n = 5;		
	int* p = &n;
	*p = *p + 64;
	int* q = p;	
	
	return 0;
}

在这里插入图片描述


左右程序效果相等

int main()				int main()
{						{
	int n = 5;				int n = 5;
	int* p = &n;			n = n + 64;
	*p = *p + 64;			
	int* q = p;				return 0;
						}
	return 0;
}

这个傻蛋程序只是为了单纯展示指针,事实上,除非在必要情况下否则尽量不要使用指针


来看需要使用指针的情况

void swap(int a, int b)
{
	int temp = a;
	a = b;
	b = temp
}

int main()
{
	int x = 6;
	int y = 9;
	swap(x, y);		/ swap()接收x,y的'值'然后执行,不交换x,y本身的数据
}
void swap(int* pa, int* pb)
{
	int temp = *pa;
	*pa = *pb;
	*pb = temp
}

int main()
{
	int x = 6;
	int y = 9;
	swap(&x, &y);	/ swap()接收x,y的'内存地址'然后执行,住户没换,门牌号换了,等价于值交换了
}

指针 pointer引用 reference的对比:
(双向和单向的区别,因为指针多出的功能,自然地它需要多出语法来区分功能)

	// pointer
	int* ptr = &n;	/ 初始化声明
	int* ptr;		/ 无初始化声明
	ptr = &m;		/ 改变指针
	*ptr = 69;		/ 改变目标
	
	// reference
	int& ref = m;	/ 正确,物质必须存在才能引用它
	int& ref2;		/ 错误,引用必须初始化
	ref = n;		/ 不能改变目标,这样会把n的值存储到m内

但这里却正说明了,很多时候,强大不代表最好

void swap(int& a, int& b)	/ 更加清晰明了,不容易搞砸
{
	int temp = a;
	a = b;
	b = temp
}

int main()
{
	int x = 6;
	int y = 9;
	swap(x, y);		/ swap()接收x,y的'引用'然后执行,交换x,y本身的数据
}

使用优先级潜规则:variable directly > reference > pointer


class示范
重要: ->操作符

example A

class Poop
{
public:
	int pizza;
	int cola;
	char mix;
};

int main()
{
	Poop myPoop;
	Poop* p_Poop = &myPoop;
	int* p_Pizza = &myPoop.pizza;
	int* p_Cola = &myPoop.cola;
	char* p_Mix = &(*p_Poop).mix;		/ 此行等于 char* p_Mix = &p_Poop->mix;

	return 0;
}

example B

class Dump
{
public:
	Vec2& operator+=(const Vec2& rhs)
	{										   
		return *this = *this + rhs;
		/ 实则this1个指针,所有非静态成员函数都会自动定义this
		/ this指向成员函数所调用的成员,this可用于return自己的引用,或将自己的地址传给其它函数
		/ 非静态成员函数 = non-static member function
	}
}

再来看一下this的“去除模糊”的使用

class Dump
{
public:
	float BustAss(float x, float y) const
	{
		return x*x + y*y;	/ 参数与成员重名,return后只会是参数自乘
		return this->x*x + this->y*y;	/ 假设你想参数*成员,必须要这样
		
		/ 仍然建议永远保持成员member和参数parameter名字不同
	}
public:
	float x;
	float y;
}

example C

int main()
{
	int arr[4] = { 10, 11, 12, 13 };
	int* ptr = &arr[1];
	*ptr = 69;		/ 1169
	
	return 0;
}

example D

int main()
{
	int arr[4] = { 10, 11, 12, 13 };
	int* ptr = &arr[1];
	ptr[2] = 69;	/ 469
	
	return 0;
}

在这里插入图片描述


example E

int main()
{
	int arr[4] = { 10, 11, 12, 13 };
	int* ptr = arr;		/ 光屁股的array表现和pointer一样,arr用来定位这个数组开始的地址
	*arr = 69;			/ 1069
	ptr[2] = 69;		/ 1269

	// pointer和array的区别
	int n = 69;
	arr = &n;					/ 错误,不能改变arr目标
	int sizeP = sizeof(ptr);	/ sizeP = 4
	int sizeA = sizeof(arr);	/ sizeA = 16
	return 0;
}
请认真体会这所有结构之中的相关之美,此后我们还会遇到很多

Array求和
int sum(int* ptr, int size)
{
	int sum = 0;
	for	(int i = 0; i < size, i++)
	{
		sum += ptr[i];
	}
	return sum;
}
int main()
{
	int arr[4] = { 10, 11, 12, 13 };
	int result = sum(arr, 4);
	return 0;
}

下期预告:指针进阶

喜欢的话可以三连、打赏,以后会持续更新质量的C++教程

交流群:857043776

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值