12 - 经典问题解析一(const & 引用)

---- 整理自狄泰软件唐佐林老师课程

1. 关于 const 的疑问

  • const :什么时候为只读变量?什么时候是常量?

1.1 const 常量的判别准则

  • 只有用 字面量 初始化的 const 常量 才会进入 符号表
  • 使用 其它变量 初始化的 const 常量仍然是 只读变量
  • volatile 修饰的 const 常量 不会进入符号表
  • 编译期间不能直接确定初始值的 const 标识符 ,都被作为 只读变量 处理。

1.2 const 引用的类型和初始化变量的类型

  • const 引用的类型和初始化变量的类型相同时:初始化的变量成为只读变量
  • const 引用的类型和初始化变量的类型不同时:生成一个新的只读变量
#include <stdio.h>

int main()
{
    const int x = 1; // 字面量,符号表中
	const int& rx = x;
	int& nrx = const_cast<int&>(rx);
	
	nrx = 5;
	
	printf("x    = %d\n", x); // 符号表中直接取值
    printf("rx   = %d\n", rx);
    printf("nrx  = %d\n", nrx);
    printf("&x   = %p\n", &x);
    printf("&rx  = %p\n", &rx);
    printf("&nrx = %p\n", &nrx);
    
    return 0;
}

在这里插入图片描述

#include <stdio.h>

int main()
{
    volatile const int x = 2;
	int* p = const_cast<int*>(&x);

	*p = 6;
	printf("x = %d\n", x); // 被 volatile 修饰的 const 常量不会进入符号表 
    printf("p = %p\n", p);

	const int y = x; // 在编译期间不能直接确定初始值的 const 标识符 ,
					 // 都被作为只读变量处理
	p = const_cast<int*>(&y);
	
	*p = 7;
	printf("y = %d\n", y);
    printf("p = %p\n", p);
	
    return 0;
}

在这里插入图片描述

#include <stdio.h>

int main()
{
    char c = 'c';
	char& rc = c;
	const int& trc = c; // const 引用的类型和初始化变量的类型不同时,
						// 生成一个新的只读变量
	
	rc = 'a';
	
    printf("c   = %c\n", c);
    printf("rc  = %c\n", rc);
    printf("trc = %c\n", trc);

    printf("&c   = %p\n", &c);
    printf("&rc  = %p\n", &rc);
    printf("&trc = %p\n", &trc);
	
    return 0;
}

在这里插入图片描述

2. 关于引用的疑问

  • 引用与指针有什么关系?如何理解 “ 引用的 本质 就是指针常量 ”

2.1 指针和引用的关系

  • 指针是一个 变量
    • 值为一个内存地址,不需要初始化,可以保存不同的地址
    • 通过指针可以访问对应内存地址中的值
    • 指针可以被 const 修饰成为常量或者只读变量
  • 引用 只是一个变量的 新名字
    • 对引用的操作(赋值、取地址等)都会 传递到代表的变量
    • const 引用使其代表的变量具有 只读属性
    • 引用 必须在定义时初始化,之后无法代表其它变量

2.2 使用角度和编译器角度

  • 从使用 C++ 语言的角度来看:
    • 引用和指针没有任何的关系
    • 引用是变量的新名字,操作引用就是操作对应的变量
  • 从 C++ 编译器的角度来看:
    • 为了支持新概念 “引用” 必须要有一个解决方案
    • 在编译器内部,使用指针常量来实现 “引用”
    • 因此,“引用” 在定义时必须初始化
  • 在工程项目开发中:
    • 当进行 C++ 编程时,直接站在使用的角度看到引用,与指针毫无关系,引用就是变量的别名
    • 当对 C++ 代码进行调试分析时,一些特殊情况,可以考虑站在 C++ 编译器的角度看待引用

2.3 问题

  • 下面的代码有问题吗?

在这里插入图片描述

  • C++ 中 不支持引用数组因为数组元素的地址是 递增的
#include <stdio.h>

int a1 = 1;

struct SV {
	int& x;
	int& y;
	int& z;
};

int main()
{
	int a2 = 2;
	int* a3 = new int(3);
	
	SV sv = {a1, a2, *a3};
	int& array[] = {a1, a2, *a3};
	
	printf("&sv.x = %p\n", &sv.x);
    printf("&sv.y = %p\n", &sv.y);
    printf("&sv.z = %p\n", &sv.z);
	
	delete a3;
	
    return 0;
}

在这里插入图片描述

#include <stdio.h>

int a1 = 1;

struct SV {
	int& x;
	int& y;
	int& z;
};

int main()
{
	int a2 = 2;
	int* a3 = new int(3);
	
	SV sv = {a1, a2, *a3};
	// int& array[] = {a1, a2, *a3};
	
	printf("&sv.x = %p\n", &sv.x);
    printf("&sv.y = %p\n", &sv.y);
    printf("&sv.z = %p\n", &sv.z);
	
	delete a3;
	
    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

uuxiang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值