C++深度解析 经典问题解析 const和引用,只读变量和常量(11)【详细】
对于const的疑问
const常量的判别准则:
- 只有用字面量初始化的const常量才会进入符号表,是真正意义上的常量
- 使用其他变量初始化的const常量仍然是只读变量
- 被volatile修饰(易变的,可能发生变化的)的const常量不会进入符号表,volatile const同时修饰的标识符,得到的是只读变量。
- const引用的类型与初始化变量的类型,相同:初始化变量成为只读变量,不同:生成一个新的只读变量
只读变量和常量的区别:
归纳起来:编译期间,不能直接确定初始值的const标识符,都是只读变量。
//用字面量1初始化x,x是真正意义上的常量,并且编译器会为常量x分配4个字节的空间,x会进入了符号表
const int x = 1;
//因为使用变量初始化,所以引用rx代表一个只读变量。编译器会为常量x分配4个字节的空间,rx代表这4个字节空间的别名
const int& rx = x; //引用代表变量的别名(也就是说一段内存的别名)
引用代表变量的别名,变量的别名代表一段内存空间的别名。
const引用:
const引用使得存在的变量拥有只读属性。
把const引用初始化为常量,得到只读变量。
//用字面量1初始化x,x是真正意义上的常量,并且编译器会为常量x分配4个字节的空间,x会进入了符号表
const int x = 1;
//因为使用变量初始化,所以引用rx代表一个只读变量。编译器会为常量x分配4个字节的空间,rx代表这4个字节空间的别名
const int& rx = x; //引用代表变量的别名(也就是说一段内存的别名)
//rx代表只读变量,const_cast消除只读变量的只读属性,所以,转换后nrx是普通变量
int& nrx = const_cast<int&>(rx);
nrx = 5;//通过引用nrx,改变所对应4个字节空间的值(改变了rx和nrx)
printf("x = %d\n", x); //1 因为进入符号表,所以值不变,仍旧是1
printf("rx = %d\n", rx); //5 rx和nrx所引用的内存空间是一样的
printf("nrx = %d\n", nrx); //5
//编译器为const所修饰的标识符仍然分配空间,这空间一般不使用。通过引用或指针来使用
printf("&x = %p\n", &x); //0xbfd73668
printf("&rx = %p\n", &rx); //0xbfd73668
printf("&nrx = %p\n", &nrx); //0xbfd73668
分析:C++为了兼容C语言的特性,为const所修饰的标识符仍然分配空间,只不过这个空间一般不使用。
volatile表示易变的。
//用字面量2初始化y,但是因为volatile表示易变的,y表示只读变量
volatile const int y = 2;
//去除y的只读属性,用指针p指针y所对应的地址
int* p = const_cast<int*>(&y);
*p = 6;
printf("y = %d\n", y); //6
printf("p = %p\n", p); //0xbfd7365c
判别const所修饰的标识符,是不是常量的标准,编译期间确定它的值
//y是一个变量,得到一个只读变量z
const int z = y;
p = const_cast<int*>(&z);
*p = 7;
printf("z = %d\n", z); //7
printf("p = %p\n", p); //0xbfd73654
const引用的初始化类型不同,将得到新的只读变量
//不同类型的变量去初始化const标识符
char c = 'c';
char& rc = c; //引用rc代表变量c
//const引用的初始化类型不同(c是char,而trc是int),将得到新的只读变量
//trc代表一个只读变量
const int& trc = c;//char类型默认转换为int类型
rc = 'a';
printf("c = %c\n", c); //a
printf("rc = %c\n", rc); //a
printf("trc = %c\n", trc); //c const引用的初始化类型不同,将得到新的只读变量!!!!
全部代码如下:
#include <stdio.h>
int main()
{
//用字面量1初始化x,x是真正意义上的常量,并且编译器会为常量x分配4个字节的空间,x会进入了符号表
const int x = 1;
//因为使用变量初始化,所以引用rx代表一个只读变量。编译器会为常量x分配4个字节的空间,rx代表这4个字节空间的别名
const int& rx = x; //引用代表变量的别名(也就是说一段内存的别名)
//rx代表只读变量,const_cast消除只读变量的只读属性,所以,转换后nrx是普通变量
int& nrx = const_cast<int&>(rx);
nrx = 5;//通过引用nrx,改变所对应4个字节空间的值(改变了rx和nrx)
printf("x = %d\n", x); //1 因为进入符号表,所以值不变,仍旧是1
printf("rx = %d\n", rx); //5 rx和nrx所引用的内存空间是一样的
printf("nrx = %d\n", nrx); //5
//编译器为const所修饰的标识符仍然分配空间,这空间一般不使用。通过引用或指针来使用
printf("&x = %p\n", &x); //0xbfd73668
printf("&rx = %p\n", &rx); //0xbfd73668
printf("&nrx = %p\n", &nrx); //0xbfd73668
//用字面量2初始化y,但是因为volatile表示易变的,y表示只读变量
volatile const int y = 2;
//去除y的只读属性,用指针p指针y所对应的地址
int* p = const_cast<int*>(&y);
*p = 6;
printf("y = %d\n", y); //6
printf("p = %p\n", p); //0xbfd7365c
//y是一个变量,得到一个只读变量z
const int z = y;
p = const_cast<int*>(&z);
*p = 7;
printf("z = %d\n", z); //7
printf("p = %p\n", p); //0xbfd73654
//不同类型的变量去初始化const标识符
char c = 'c';
char& rc = c; //引用rc代表变量c
//const引用的初始化类型不同(c是char,而trc是int),将得到新的只读变量
//trc代表一个只读变量
const int& trc = c;//char类型默认转换为int类型
rc = 'a';
printf("c = %c\n", c); //a
printf("rc = %c\n", rc); //a
printf("trc = %c\n", trc); //c const引用的初始化类型不同,将得到新的只读变量!!!!
return 0;
}
结果如下:

对于引用的疑问
引用的本质就是指针常量。
指针是一个变量
- 值为一个内存地址,不需要初始化,可以保存不同的地址
- 通过指针可以访问对应内存地址中的值
- 指针可以被const修饰成为常量或者只读变量
引用只是一个变量的新名字
- 对引用的操作(赋值,取地址等)都会传递到代表的变量上,对引用的操作,就是对 对应的变量 的操作。
- const引用使其代表的变量具有只读属性。
- 引用必须在定义时初始化,之后无法代表其他变量。
在C++中,不支持引用数组:
示例程序:
#include <stdio.h>
//静态存储区
int a = 1; //全局变量
struct SV
{
int& x;
int& y;
int& z;
};
int main()
{
//栈空间
int b = 2;
//堆空间
int* pc = new int(3);
SV sv = {a, b, *pc};
//引用数组破坏了C语言的特性,数组的每个元素都是彼此相邻的排放
// &array[1] - &array[0] = ? 所期望的结果是4
//C++不支持引用数组!!!!!
//int& array[] = {a, b, *pc}; //错误,数组的每个元素在内存里是顺序存放的,数组的地址是递增的
printf("&sv.x = %p\n", &sv.x);
printf("&sv.y = %p\n", &sv.y);
printf("&sv.z = %p\n", &sv.z);
//释放堆空间
delete pc;
return 0;
}
结果如下:

所以在C++中,不支持引用数组,因为会使得相邻数组元素的地址之差,不是我们所期望的!!!!
小结:
指针是一个变量。
引用是一个变量的新名字。
const引用能够生成新的只读变量。
在编译器内部使用指针常量实现“引用”。
编译时不能直接确定初始值的const标识符都是只读变量。

【详细】&spm=1001.2101.3001.5002&articleId=85048755&d=1&t=3&u=473e59e638ad47eb8080b41a1fad8a30)
2949

被折叠的 条评论
为什么被折叠?



