指针和引用

指针和引用——与对象地址相关的复合类型
内存地址
程序运行时,代码和需要的数据都被存储在内存中
内存是有序的字节序列,每个字节都有唯一的地址,使用该地址可以确定字节的位置,用以存储和获取数据
直接访问和间接访问
通过变量的名字直接访问为程序中定义的变量分配的内存单元,存取变量的值
使用变量的内存地址找到存放数据的单元,间接访问其中的内容

指针

指针的特点
指针持有一个对象的地址,称为指针“指向”该对象
通过指针可以间接操纵它指向的对象
定义指针变量的语法
类型 *指针变量
取地址运算符“&”
指针存放指定类型对象的地址,要获取对象的地址,使用取地址运算符“&”
指针解引用运算符“ * ”
如果指针指向一个对象,则可以通过指针间接访该对象,使用指针解引用运算符“ * ”
指向对象的指针
指向一个对象的指针有两个存储单元与之相关
一个是指针自己的存储单元,里面存放着所指对象的地址;
另一个就是指针指向的对象的存储单元,里面存放该对象的值。
可以定义存放指针对象的地址的指针

#include <iostream>
using namespace std;
int main( )
{
 int ival=1024;
 int *pi=&ival;
 cout << " sizeof(pi):" << sizeof(pi) << endl; //指针在内存中所占大小
 cout << " sizeof(ival):" << sizeof(ival) << endl; //ival在内存中所占大小
 cout << " &pi:" << &pi << endl; //指针在内存中的地址
 cout << " pi:" << pi << endl; //指针中存放的内容,即ival的地址
 cout << " &ival:" << &ival << endl; //ival的地址
 cout << " *pi:" << *pi << endl; //指针所指内存中存放的内容,即ival的值
 cout << " ival:" << ival << endl; //ival的值
}

指针的类型
每个指针都有相关的类型,需要在定义指针时指出
type* pointer
指针的值
指针不能保存非地址值,也不能被赋值或初始化为不同类型的地址值
空指针
指针值为0时是一个空指针,即不指向任何对象的指针

// 生成空指针的2种方法 
int *p1 = 0;       
int *p2 = NULL;

使用指针的注意事项
定义指针时,应该对指针进行初始化
指针的运算
同类型的指针可以进行相等(==)或不相等(!=)的比较操作,比较的结果是布尔类型
指针可以进行加或减整数值的算术运算
自增、自减运算适用于指向数组元素的指针
通用指针void*
void*指针
可以持有任何类型的地址值,即通用指针
相关的值是个地址,但是该地址保存的对象类型不知道
不能操纵void指针指向的对象,只能传送该地址值或者和其他地址值进行比较
不允许void指针到其他类型指针的直接赋值

int a = 10;
char ch = 'k';
void* pv = &a;  //不正确
pv = &ch;   //不正确
int* pi = pv;   //不正确

指针的应用
构建链式的数据结构,如链表和树;
管理程序运行时动态分配的对象;
作为函数的参数。
静态和动态内存分配在语法上的主要区别
静态对象是有名字的变量,可以直接对其进行操作;动态对象没有名字,要通过指针间接地对它进行操作。
静态对象的空间分配与释放由编译器自动处理,动态对象的空间分配与释放必须由程序员显式地管理。
动态内存管理方法
C++通过new和delete运算符进行动态存储空间的管理
new运算符
在堆上动态分配空间,创建对象,并返回对象的地址
一般将new返回的地址保存在指针变量中,以便间接访问堆上的对象。
new表达式的三种形式
<1>.分配单个对象:new 类型 或者 new 类型(初始值)

int* ip1 = new int;
   //在堆上分配一个int类型的对象,返回它的地址
*ip1 = 512; 
   //堆上分配的这个对象只能通过指针间接操作
int* ip2 = new int(100);
   //在堆上分配一个int对象,
   //初始化为100,返回其地址

<2>.分配多个连续存储的对象:new 类型[数组大小]

int* ipa = new int[100];
//在堆上分配一个大小为100的int数组并返回数组的首地址

不能对数组进行显式的初始化
数组大小不必是常量,是数组元素的个数,不是字节数
用new分配数组时,并未得到一个数组类型的对象,而是得到一个数组元素类型的指针
<3>.定位new,在指定位置分配空间:new (指针) 类型;
必须包含标准库头文件

#include <new>
char* buf = new char [1000]; 
  //预分配一段空间,首地址在buf中保存
int main(){
int* pi = new (buf) int; 
  //在buf中创建一个int对象,此时不再重新从堆上分配空间
}

delete运算符
堆上的空间在使用后必须释放,否则会造成内存泄漏
即动态内存空间使用后未回收,导致一直被占据
释放new分配的单个对象 delete 指针;

int* ip = new int;
... //不再使用这个int对象时,释放内存
delete ip; 
//释放指针指向的int对象,将空间归还给动态存储区

释放new分配的数组 delete[] 指针;

int* pa = new int[100]; 
... //不再使用这个数组时,释放内存
delete[] pa; 
//释放指针pa指向的数组,将空间归还给动态存储区

定位new没有对应的delete表达式
空悬指针
delete后的ip不是空指针,而是“空悬指针”,即指向不确定的单元
delete之后,继续通过ip间接使用这个单元是非法的,会引起不可预料的运行错误
引用
引用又称为别名,它可以作为对象的另一个名字;
通过引用可以间接地操纵对象;
在程序中,引用主要用作函数的参数。
引用由类型标识符和一个说明符(&)来定义
type& refVariable = leftValue;
引用必须被初始化,初始值是一个有内存地址的对象
引用的初始化和一般变量的初始化不同
1.一般在初始化变量时,初始值会被复制到新建的对象中
2.定义引用时,程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用
3.一旦初始化完成,引用将和它的初始值对象一直绑定在一起
4.因为无法令引用重新绑定到另外一个对象,所以引用必须初始化
使用左值引用时注意
引用并非对象,是为已存在的对象所起的另一个名字
引用只能绑定到对象(有内存地址)上,不能与字面值或某个表达式的计算结果绑定在一起。
引用vs指针
1.指针的定义形式
类型 *指针变量;
指针保存指定类型的对象的地址,一个指针可以指向同类型的不同对象

int x = 10, y = 20;
int *pi; //未初始化
pi = &x; 
pi = &y; 

.引用的定义和初始化
类型 &引用名 = 初始值;
引用是一个对象的别名,定义引用时必须用有内存地址的对象初始化
引用在初始化之后,一直指向该对象

int a = 10, b=20;
int &ri = a; 
ri = b;  

2.指针通过解引用(*)运算间接访问指向的对象
引用作为对象的别名,可以直接访问对象

int x, a, *pi;
pi = &x;
*pi = 30;  // x=30
int &ri = a;
ri = 40;  //a=40 

3.有空指针
指针可以不指向任何对象,其值为0,表示空指针
没有空引用
引用必须指向一个对象,而且一直指向该对象,不存在“空”引用。
引用的值如果为0,表示它指向的单元值为0

int a, *pi;
pi = 0;  // pi是空指针,不指向任何对象
int &ri = a;
ri = 0;  //a=0

4.赋值
指针之间的相互赋值会改变指向关系
引用之间的相互赋值是它们指向的对象之间的赋值,引用关系本身并不改变

int x = 100, y = 20;
int *p1 = &x, *p2 = &y;
p1 = p2;  // p1=&y, p1和p2都指向y
int &r1 = x, &r2 = y; 
r1 = r2;  // x = y, r1仍是x的引用

const限定指针
1.指向const对象的指针(非const )
const type cp; 或者type const cp;
cp是指向常量的指针,它所指向的内存中的内容不可以改变,即
cp的值不能改变
2.指向非const对象的const指针
type
const cp = initAddressValue;
cp是常量指针,初始化后值不能改变,指向固定的单元
3.指向const对象的const指针
const type* const cp = initAddressValue;
const限定引用
const限定的左值引用不可修改
const引用可以绑定到const对象
不能用非const引用指向const对象
const左值引用可以绑定到非const对象
但是const引用不能用来修改它所绑定的对象
数组元素和地址
//一维数组元素在内存中按下标顺序依次存放
一维数组a[n]的元素a[i]在内存中地址是a+i。
//多维数组在内存中按行序存储
二维数组a[m][n]的元素a[i][j] 在内存中的地址是a+(i*n+j)
使用指针访问数组时需要控制指针的范围,确保指针指向数组的元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值