C++笔记第八章:指针


这一章主要介绍了指针与内置数组的关系

  • 指针变量:某一变量储存的值时另一个同类型变量的内存地址
  • 指针变量的数据类型:由数据类型+*组成。
    • 如:int* iPtr,但是书中是int *iPtr,这样会造成一些概念上的混淆。
  • 指针的初始化:iPtr = &i,其中i必须是一个已经声明的变量的内存地址。
  • 指针的操作:对指针的操作会反应到其指向变量上。
    • *iPtr的操作会修改I的值。
  • 指针的锁:基于const指针与const数据的四种组合。

1.指针的创造

1.1 指针变量的声明

变量声明:
 与函数声明类似,变量声明告诉编译器,该标识符对应的数据类型为何种,并为其预留内存空间。
(Markdown语言中,一定要将markdown和html语言放在同一行,就可以一起执行)

int main()
{
	//变量声明:
	int i = {3};
	int* iPtr;  //与书中不同,不要理解成“*”+标识符,而是立即成数据类型+“*”。
}
  •  这里,我们指明了指针变量iPtr的数据类型为int*类型。一般而言,无论何种数据类型的指针变量,系统为其分配的内存空间大小都是一定的。原因在于指针只储存内存地址这一数据。我们可以对在C++中使用以下命令查看指针所占的内存空间大小。

1.2 指针变量的空间大小

 无论何种指针数据性质,其均只储存内存地址。因此,其占据的内存空间极小,同时大小一致。如在Win10 64位系统的VS编译器中,指针变量仅有8个字节


运算符sizeof():
 1. sizeof()可以获得标识符或数据类型所占的空间大小。具体的使用方法如下:
  1.1 不适用括号直接在标识符前面使用sizeof
   如:sizeof c (c为标识符)
  1.2 对于数据类型需要使用括号
   如:sizeof(char)

#include<iostream>
int main()
{
	//初始化指针变量
	char* cPtr;
	long double* ldPtr;
	
	//打印大小
	std::cout<<"sizeof(char*)"<<sizeof cPtr<<std::endl; //结果为8字节
	std::cout<<"sizeof(long double*)"<<sizeof(ldPtr)<<std::endl; //结果为8字节
	//为了避免错误,建议无论对数据类型还是标识符,都使用带括号的sizeof()
}

1.3 指针的初始化

 在我们声明完指针变量,使编译器在内存空间中,为标识符预留适合它声明数据类型的内存地址后。我们可以对指针变量进行初始化。

  • 若我们在声明的时候没有赋值,我们仍可以使用std::cout<<Ptr<<*Ptr来打印未初始化的指针变量,但是该变量不能直接进行*Ptr = 123这种的赋值(初始化)操作。编译器会报错。
  • 在对指针变量进行初始化的时候,对象必须是一个变量标识符标示的内存地址。
int main()
{
	int a = 123;
	//指针变量声明
	int* aPtr;
	//指针变量初始化,初始化必须是一个变量标示的内存地址
	aPtr = &a;
}

1.4 指针的const限定

通过在对指针声明与赋值的时候加入const,对以下两个对象进行const

  • 其一,指针变量const。即:指针只能指向固定地址无法修改。
  • 其二,指针指向的值为const。即:从指针这条路线到值是const(不通的,无法修改的)
修改
初始化时分配内存地址
根据不同数据类型进行解析
指针A
非指针变量B内存地址
地址中的数据
非指针变量B

我们可以限定指针的权限。根据指针变量与数据可以分为以下四个情况:

  • 非const指针,非const数据
  • 非const指针,const数据
  • const指针,非const数据
  • const指针,const数据

1.4.1 const数据,非const指针

在这种情况下,通过指针指向数据的这条线是const的。

  • 即我们无法通过指针变量的路线来修改数据。
不可修改
初始化时分配内存地址
根据不同数据类型进行解析
指针A
非指针变量B内存地址
地址中的数据
非指针变量B
  • 在下面的情况中,由于int i = 3;是非const。我们仍可以通过iiPtr2来修改数据。。
#include<iostream>

int main()
{
	int i=3;
	const int* iPtr1 = &i; //指针非const,数据const。
	int* iPtr2 = &i; //指针非const,数据非const
}

我们将const int* iPtr1 =&i这个语句从声明初始化拆开来看

const int* iPtr1; 
iPtr1 = &i;

在一般的数据类型中,如const int i=3;

  • 可以理解为,该内存地址中的值不可修改。
  • 不要理解成,无法通过标识符i来修改,否则我们可以通过下面的方法来修改内存地址中的值。但是事实上程序会告诉你"const int *"类型的值不能用于初始化"int *"类型的实体
const int i = 3;
int* iPtr = &i; //在&位置会进行报错。

n.指针与引用的差异。

虽然引用和指针都使用&

在指针中,我们有int* iPtr = &i表示方式,这里的&提取的是i的内存地址。

在引用中,

但与指针不同,引用变量是对同一内存地址集用另一种标识符进行命名。

n.1 指针中的地址

指针中,我们使用&+标识符来提取标识符对应值的内存地址。

int main()
{
	int i;
	int* iPtr = &i;
}
  • int* iPtr = &I;
    在这里iPtr储存了i的内存地址信息。

n.2 引用中的&


引用中我们用数据类型+&+空格+标识符来声明引用变量。

  • 引用变量在声明的时候必须进行初始化
  • 引用变量在被初始化以后不能在重新引用新的对象
  • 注意引用跟指针一样int*int&都是一种数据类型。前者表示后面所跟的标识符的数据类型(可以想象成容器,即装入固定形状的盒子)是指针类型或者引用类型数据。
int main()
{
	int A=123;
	int& B=A; //书中写成 int &B,虽然程序也能够识别,但是会造成概念的混淆。
}

实际上,标识符A与标识符B都是标示同一个内存地址中的值。具体的情况如下图所示:

  • 引用变量是一个别名,也就是说某个已存在的变量的另一个名字。
标识符A
内存地址的值:123
标识符B
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值