程序设计B笔记——指针和引用

本文详细介绍了C++中的指针和引用,包括指针的类型、取地址与解引用运算、空指针的使用、动态存储空间管理以及new和delete运算符。此外,还探讨了引用的定义、初始化、引用关系以及const限定在指针和引用中的应用。最后提到了begin()和end()函数在数组操作中的作用。
摘要由CSDN通过智能技术生成

指针

每个指针都有相关的类型,要在定义指针时指出

类型 *指针变量;

取地址运算符“&”

指针存放指定类型对象的地址,要获取对象的地址,使用取地址运算符“&”

int ival = 120;
int  *pi = &ival;	
		// pi存放int变量ival的地址
		// 或者说pi指向ival
char ch = 'a', *pc = &ch;
		// pc指向字符型变量ch

指针解引用运算符“*”

如果指针指向一个对象,则可以通过指针间接访该对象,使用指针解引用运算符“*”

int x = 100, y = 20;
int *pi = &x;
*pi = y;		
		// 间接操作pi指向的x,即x = y
#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的值

空指针

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

//不能写成下面的样子:
int zero = 0;
int *p4 = zero;

使用指针的注意事项

  • 定义指针时,应该对指针进行初始化
  • 指针的运算
    • 同类型的指针可以进行相等(==)或不相等(!=)的比较操作,比较的结果是布尔类型
    • 指针可以进行加或减整数值的算术运算
    • 自增、自减运算适用于指向数组元素的指针

存储空间分配策略

静态(编译时)分配空间
编译器在处理程序源代码时分配内存;
效率高,灵活性差,运行前就要知道程序需要的内存大小和类型
动态(运行时)分配空间
程序运行时调用运行时刻库函数来分配内存;
占用程序运行时间,更灵活

动态存储空间管理

new运算符
  • new表达式的三种形式
    • 分配单个对象:new 类型 或者new 类型(初始值)

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

    • 定位new,在指定位置分配空间:new (指针) 类型;

new (指针) 类型;

  • 定位new在指针指向的空间中创建一个指定类型的对象
  • 程序员可以预先分配大量的内存,以后通过定位new表达式在这段内存中创建对象
  • 使用定位new,必须包含标准库头文件
#include <new>
char* buf = new char [1000];	
		//预分配一段空间,首地址在buf中保存
int main(){
int* pi = new (buf) int;	
		//在buf中创建一个int对象,此时不再重新从堆上分配空间
}
delete运算符
  • new运算符分配的空间用delete运算符释放
    • 释放new分配的单个对象的delete形式 delete 指针;

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

    • 定位new没有对应的delete表达式

空悬指针

  • 执行delete运算后,指针ip指向的空间被释放,不能再使用ip指向的内存,但是ip这个指针变量自己的存储空间不受影响
  • delete后的ip不是空指针,而是“空悬指针”,即指向不确定的单元
  • delete之后,继续通过ip间接使用这个单元是非法的,会引起不可预料的运行错误

引用

在程序中,引用主要用作函数的参数。

引用的定义和初始化

  • 引用由类型标识符和一个说明符(&)来定义type& refVariable = leftValue;
  • 引用必须被初始化,初始值是一个有内存地址的对象

引用关系

  • 引用一旦初始化,就不能再指向其他的对象,对引用的所有操作都会被应用在它所指向的对象上
  • 引用的初始化和赋值不同
  • 初始化时引用被“绑定到”一个对象;
  • 赋值时,引用被作为所绑定对象的别名
  • 引用只能绑定到对象(有内存地址)上,不能与字面值或某个表达式的计算结果绑定在一起。
  • 引用并非对象,是为已存在的对象所起的另一个名字

const限定指针

  • 指向const对象的指针(非const )
    const type *cp;或者type const *cp;
    • cp是指向常量的指针,它所指向的内存中的内容不可以改变,即*cp的值不能改变
  • 指向非const对象的const指针
    type* const cp = initAddressValue;
    • cp是常量指针,初始化后值不能改变,指向固定的单元
  • 指向const对象的const指针
    const type* const cp = initAddressValue;

指向const对象的指针

const int ival = 1024;
int *pi = &ival;		
	//错误:试图将一个const地址赋值给一个非const指针
const int ival = 1024;
const int *pi = &ival;			//OK
//或者这样写:
int const *pi = &ival;			//OK
*pi = 500;  
	//错误:因为*pi是一个const int

C++允许将一个非const地址赋值给const指针

int ival =1024;
const int *pi = &ival;
ival = 500;
		//OK,ival没有被限定为const,可以改变
*pi = 500;  
		//错误: 不可以通过pi改变ival,因为pi是const int*

指向常量的非const指针

int ival = 1024;
int* const pi = &ival;
pi所在内存中的值不能改变
pi指向的内存中的内容可以变

指向const对象的const指针

  • 在pi的定义中
    • 第一个const限定int,表示指针指向的单元是常量;
    • 第二个const限定pi,表示指针的值也是一个常量
    • 指针pi所在内存的值不允许改变,它所指向内存的值也不能改变

const限定引用

  • const限定的左值引用不可修改
    • const引用可以绑定到const对象
    • 不能用非const引用指向const对象
const int ival = 5;
const int &r1 = ival;		
		//正确:引用和所引用的对象都是const int
r1 = 10;				
		//错误:r1是const的引用,不能修改
int &r2 = ival;			
		//错误:不能用非const引用指向const对象
  • const左值引用可以绑定到非const对象
    • 但是const引用不能用来修改它所绑定的对象
int ival = 10;			
const int &r1 = ival;
		//正确:允许将const引用绑定到非const对象上
ival = 20;	//正确
r1 = 20;	//错误:r1是const引用,不能修改
  • const左值引用可以绑定到生成右值的表达式
    • 可以用任意表达式初始化const引用,只要表达式的结果能转换成引用的类型即可
const int &r2 = r1 * 2;		//正确:r2是const引用
int &r3 = r1 * 2;			//错误:r3是普通非const引用
int& r4 = 10;			
		//错误:r4是普通非const引用,字面值10不可寻址
const int &r5 = 10; 		//正确:r5是const引用
		//编译器生成一个值为10的临时对象,r5指向这个对象
  • const限定引用的含义
    • const引用仅对引用自己可参与的操作进行了限定,对所指向的对象本身是不是常量未作限定。因为指向的对象也可能不是const,所以允许通过其他途径改变它的值
int ival = 5;
const int &r1 = ival;		
		//正确:r1可以绑定ival,但不能通过r1修改ival
int &r2 = ival;
r1 = 0;					
		//错误:r1是const引用,不能修改
r2 = 0;					
		// r2并非常量,可以修改ival为0

begin()和end()

  • 库函数begin()和end()
    • 让指针在数组上的使用更简单更安全
    • 在头文件<iterator>中定义

用法:

  • begin(数组名)

    • 返回指向数组第一个元素的指针
  • end(数组名)

    • 返回指向数组最后一个元素的下一个位置的指针
//在数组arr 中查找第一个负数:
int *pb = begin(arr), *pe = end(arr);
while(pb != pe && *pb >= 0)
++pb;

//逐个输出数组元素的循环
for(int p = begin(arr); p!= end(arr); ++p)
cout << *p << "\t";
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值