C++(9)--裸指针、智能指针、引用


《老九学堂C++课程》《C++ primer》学习笔记。《老九学堂C++课程》详情请到B站搜索《老九零基础学编程C++入门》
-------------简单的事情重复做,重复的事情用心做,用心的事情坚持做(老九君)---------------

1.裸指针的基本概念

指针是一个值为内存地址的变量(数据对象)。也就是说指针它一样是一个变量,只不过该变量中存放的是另一个对象的内存地址,存放另一个对象的地址的操作又叫指向了该对象。
裸指针相对于智能指针而言,智能指针的使用详见part 5

  1. 变量名–地址的助记符, 指针–存放内存地址

  2. 定义指针时不赋初值,该指针叫野指针。强烈建议初始化所有指针/尽量等定义了变量之后再定义指向它的指针.

  3. 指针指向的对象可以改变(可以通过赋值–去地址符号改变指针的内容)

  4. 指针类型与指向对象的类型匹配

  5. 裸指针需要手动释放,否则会造成内存泄漏

1.1 裸指针的声明*/初始化&

裸指针声明 --仅声明不初始化的指针是非常不安全的,所以推荐声明完就初始化。

数据类型 * 指针变量名     // 定义一个指向(数据类型)变量的指针
int *ptr_num;
int *ptr_name;
int *money_ptr;
double *p_price;

注意:星号靠前靠后都是定义指针型变量,建议靠后结合知名该变量是指针。

int* a,b,c; //只有a为指向int 类型变量的指针,b、c是一般的int 型变量
int *a, *b, *c; //定义了3个指向int 类型变量的指针

裸指针初始化–取地址符号&,取变量的地址赋值给指针变量

int year;
year = 2021;       // year 对应的变量块中存放数2021
int *ptr_year;     // 声明一个指针变量
ptr_year = &year;  // 将变量year的地址出来赋给指针变量,我们说的是ptr_year指向了year这个变量

1.2 操作裸指针–间接运算符*

操作裸指针–间接运算符*
间接运算符*作用于指针变量,取变量中的地址,然后对该地址对应的内存空间进行操作

int num = 1024;
int *ptr_num;
ptr_num = \#
*ptr_111;  //等价于 num = 111;

注意:指针声明之星号 和 间接运算符之星号 的作用完全不同

1.3 裸指针使用 demo–指向一个简单变量

int main(){
	double num = 1024.5;
	double *ptr_num = #
	cout << "ptr_num 的值: " << ptr_num << "\t" << &num << endl;
	cout << "ptr_num指向空间的值: " << *ptr_num << endl;
	return 0;
}

输出:

ptr_num 的值: 0x7ffee273f630   0x7ffee273f630
ptr_num指向空间的值: 1024.5

demo2:字符指针在输出时候的注意事项

int mian(){
	char ch = 'a';
	char *ptr_ch = &ch;
	// 默认以字符串的方式打印字符(char 型指针被默认为带有间隔操作符号)       
	cout << ptr_ch << "\t" << *ptr_ch << endl;
	// 强制转换成字符型指针(输出地址,void * 任意的地址类型)
	cout << (void * )ptr_ch << "\t" << *ptr_ch << endl;
	return 0;
}

1.4 空指针–nullptr

空指针: 不指向任何对象指针。
作用: 初始化指针,避免出现野指针。
提示: 在使用一个指针前可以检查它是否为空。


int *ptr1 = nullptr;        // c++ nullptr 字面值常量 =0, 可以被转换成任何类型的指针
int *ptr2 = 0;
                        
# include <cstdlib>        // c 语法空指针
int *ptr3 = NULL

1.5 特殊指针–void *ptr

一种特殊的指针类型,可以存放各种类型变量的地址

注意1:void *指针不能用来访问地址所指向的对象(即用* 取地址对应的内容)
void 使用技巧: 和别的指针比较、作为函数的输入输出、赋值给另一个void 指针

void 指针使用示例

int main(){
	// void 指针
	double objNum = 3.14;
	double *ptr_obj = &objNum;
	void *vptr_obj = &objNum;
	cout << (vptr_obj == ptr_obj) << endl;
	return 0;
}

2.指针和引用–引用定义&

引用:对象的一个别名,引用访问变量时直接用引用名就可以了,不需要和指针一样用*。

引用的定义

int int_val = 1024;
int& refValue = int_val; # 定义了变量int_val的引用refValue

引用的使用 :和所有的一般变量一样使用即可

int num = 108;
int& rel_num = num;
rel_num = 118;               // 直接使用引用对变量赋值
cout << &num << '\t' << &rel_num << endl;
// 输出 操作的是同一块内存空间,在使用数组或者对象的引用时,才会凸显其优势
0x7ffee750f60c  0x7ffee750f60c

常量引用: 一般情况下常量的引用是错的,但是如果一定要定义一个常量的引用给可以使用const

double ref = 100.0;//❌
const double ref = 100.0;//☑️

引用和指针的关系

  1. 引用是对指针的简单封装,底层仍然是指针。
  2. 引用在获取地址时,编译器内部会进行* 操作。
  3. C++提倡使用引用,而少用指针
  4. 引用的优势-效率更高。指针赋值时的取地址符号&会验证地址的有限性(编译器内部机制?)而引用不需要,所以引用使用起来效率更高。

注意事项:

  1. 引用只能绑定在对象上,不能与字面值或者某个表达式的计算结果绑定在一块。
  2. 引用都必须初始化,所以引用使用之前不需要测试其有效性。

3.指针和数组

数组数据是一块连续的内存地址,数组名就是这块连续内存空间的首地址

3.1 数组指针的定义

int main(){
	double score[] = {11, 22, 33, 44, 55};
	double *ptr_score = score;    // 指向数组的指针,不需要取地址符号
	cout << sizeof(score) << '\t' << sizeof(ptr_score) << endl;
	cout << ptr_score[2] << endl;    // 数组指针可以像数组名一样使用下标操作数组
	return 0;
}
// 输出
40      8          # 数组名对应的数据类型为double[5]sizeof 输出时是4033

3.2 数组指针递增/递减操作

指针的++,–被视为指针的移动操作,移动下一个/上一个基本单位

int main(){
	double score[5] = {98, 87, 65, 43, 76};
	double *ptr_score = score;
	for(int i = 0; i < 5; i++){
		cout << *ptr_score++ << endl;        // 
	}
	return 0;
}

3.3 指针与数组使用的一些注意点

int num[50]; //num数组名,也可以理解成数组的首地址
// num的值和&num[0] 的值一致
// 数组第i+1个元素地址可以表示为:&num[i+1] num + i + 1
// 数组第i+1个元素可以表示为: num[i+1] 或者 *(num+i+1)
// 为指向数组的指针赋值
int *ptr_num = num;
int *ptr_num = &num[0];
//指针变量也可以指向数组元素
int *ptr_num = &num[4]
int *ptr_num = num + 4
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值