C++基础—const与指针


一、const与指针

1.const在C和C++中的区别

【注】const在C和C++中的使用方式不同,C语言中,使用const修饰变量时,是以变量为主的;但是在C++中,const修饰变量,是以“常性”为主的,也就是说,使用const定义变量之后,是以常性为主的,遇见常变量会用值去替换掉

常性替换是在编译阶段进行替换

#include <stdio.h>
// C  const
int main()
{
	const int n = 10;  // C语言中const修饰变量时,以变量为主,也就是说,const针对的是变量
	int arr[n] = { 1,2 };  // C语言中此定义错误,因为其会认为n就是一个变量,虽然加了const修饰,仍然是变量,定义数组时数组大小是一个大于零的整形常量,
	// 上述定义会出现类型错误,
	return 0;
}

// C++  const
#include <iostream>
using namespace std;
int main()
{
	const int n = 10;  // C++在修饰变量的时候,是以“常性”为主
	int arr[n] = { 1,2 };  // 在C++中此定义合法,会用整数值10取替换n,等价于:int arr[10] = { 1,2 };
	return 0;
}

1.1 如果在C语言中使用const去定义变量,然后再去定义数组,则会提示:类型错误

因为C的编译器会认为n是一个变量,即使用const去修饰,其仍然是一个变量,只不过const限制了其“写”操作
在这里插入图片描述

const int n = 5;
int b = n; // C语言中,从变量n这个内存空间取值赋值给整形变量b,是需要访问内存空间
int b = n; // 对于C++,在编译的过程中,遇见n就会将其替换成5

1.2 C编译

按照C的编译方法,虽然a用const修饰,但是可以通过p去改变a的值,在对内存进行访问,将a的值100(通过p去修改,此时为100)赋值给b,b的值也是100;所以按照C的编译方式,输出的结果为:100 100 100
在这里插入图片描述
【注】b = a; // C编译时,会借助一个“临时空间”,先将a的值取出来存放在临时空间,在将临时空间的值赋给b

1.3 C++编译

在这里插入图片描述
但是使用C++的方式编译,输出的结果为10 10 100

  1. *p=100; // 将 *p的值改为100
  2. b = a; // C++编译时,直接将a的值替换成10,然后再将10赋值给b
  3. 所以输出为:10 10 100

【注】C++编译时,遇见const修饰的变量时(直接使用常变量这个值得时候),会先将其替换成具体的数值

二、const和指针的关系

1. 常变量与指针

#include <stdio.h>
int main()
{
	int a = 10, b = 10;
	int* p1 = &a;  // p1是一个普通指针
	const int* p2 = &a;  // 指向为常性(解引用为常性)const修饰的是“*”
	//int const* p2 = &a;  // 等价于const int* p2 = &a
	int* const p3 = &a;  // 指针变量自身为常性(const修饰的是指针p3)
	const int* const p4 = &a;  // 指向(解引用)和指针变量自身都为常性
}

int main()
{
	int a = 0;
	int* p1 = &a;  // OK
	const int* p2 = &a;  // OK
	int* const p3 = &a;  // OK
	const int* const p4 = &a;  // OK
	return 0;
}

对于使用C方式编译:

// 按照C编译方式,a为一个常变量,丢弃了“写”操作,只读
int main()
{
	const int a = 10;
	int* p1 = &a;  // error  编译不通过,因为可以使用普通指针解引用去改变a的值 --- 能力扩张
	const int* p2 = &a;  // ok  const修饰指向(*),所以不能通过p2解引用去修改a的值,但是指针p2本身可以修改
	int* const p3 = &a;  // error  const修饰指针p3,不允许修改p3,但是其指向,也就是通过对p3解引用修改a的值  --- 能力扩张
	const int* const p4 = &a;  // ok 指针本身和其指向均不能被修改
	int* p5 = (int*)&a;  // 强转,C语言中的“强盗”,虽然编译可以通过,但是不安全
}

2. 同类型指针的赋值兼容规程

// C编译方式
int main()
{
	int a = 10, b = 20;
	int* p = &a;  // 定义一个普通指针p指向a的地址
	int* s1 = p;  // ok  定义一个普通指针s1指向p指向的地址,也就是s1和p都指向a的地址
	const int* s2 = p;  // ok  const修饰指向,能力缩小
	int* const s3 = p;  // ok  指针s3为常性,但可以通过解引用修改a的值(允许)
	const int* const s4 = p;  // ok
}

3. 练习

练习1:

int main()
{
	int a = 10, b = 20;
	const int* p = &a;  // const修饰指向,不能通过对p解引用去修改a的值,但是可以修改指针p本身
	int* s1 = p;  // error  能力扩张,
	const int* s2 = p;  // ok  const修饰指向,即不能通过s2去修改a的值(s2和p都指向a),但是s2本身可以修改,s2的修改不影响p
	int* const s3 = p;  // error  const修饰指针s3,即可以通过对s3解引用去修改a的值(不允许),但s3本身不允许被修改
	const int* const s4 = p;  // ok
}

练习2:

int main()
{
	int a = 10, b = 20;
	int* const p = &a;  // const修饰指针p,即p本身不允许被修改,但是其指向可以被修改
	int* s1 = p;  // ok  定义一个指针s1指向a(和p都指向a),可以通过对s1解引用去修改a的值,也可以对s1本身进行修改,不会影响p
	const int* s2 = p;  // ok  const修饰指向,即不允许通过对s2解引用修改a的值,但是s2可以被修改,不影响p
	int* const s3 = p;  // ok  const修饰s3,即不允许修改s3本身,但是可以通过对s3解引用去修改a的值
	const int* const s4 = p;  // ok
}

总结

  1. 能力强的指针赋值给能力收缩的指针(能力收缩,允许)
  2. 能力弱的指针不能赋值给扩张的指针(能力扩张,不允许)
  3. 特别重要的一点就是,编译方式的不同,会导致不同的结果
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值