关键词: const常量判别准则、引用的C++解释和编译器解释
1. 关于const的疑问:const什么时候为只读变量?什么时候是常量?
- const常量的判别准则:
- 只有用字面量初始化的
const常量才会进入符号表 - 使用其他变量初始化的
const常量仍是只读变量 - 被
volatile修饰的const常量不会进入符号表
总结:在编译期间不能直接确定初始值的const标识符都被作为只读变量处理。
-
const引用的类型与初始化变量的类型
相同:初始化变量成为只读变量
不同:生成一个新的只读变量
编程说明:const典型问题分析
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
const int x = 1; // x为常量,因为x用字面量初始化, 编译期间能确定初始值,其值在符号表中,编译器也会为x分配一段内存空间
const int& rx = x; // rx为只读变量,其所对应的内存空间为编译器为x所分配的内存空间
int& nrx = const_cast<int&>(rx); // nrx消除了rx的只读属性,为一个普通的变量
nrx = 5;
cout << "x = " << x << endl; // x的值在符号表中读取,因此输出为1
cout << "&x = " << &x << endl; // x的地址为编译器为x分配的内存空间
cout << "rx = " << rx << endl; // rx的值为内存空间中的值,由于nrx改变了内存空间的值,因此此处的rx的值为5
cout << "&rx = " << &rx << endl; // rx的地址为x的地址
cout << "nrx = " << nrx << endl; // nrx为普通变量,可以出现在赋值符号的左边进行赋值,赋值后,对应的内存空间中的值发生改变
cout << "&nrx = " << &nrx << endl; // nrx的地址为x的地址
volatile const int y = 2; // y为只读常量,其值可以通过指针或引用来改变
int* p = const_cast<int*>(&y); // 用指针p来指向y
*p = 10; // 给*p赋值
cout << "y = " << y << endl;
cout << "*p = " << *p << endl;
cout << "p = " << p << endl;
char c = 'c';
char& rc = c;
const int& trc = c; // 由于类型不同, 会生成一个新的只读变量。
int& itrc = const_cast<int&>(trc);
rc = 'a';
itrc = 'd';
cout << "c = " << c << endl;
cout << "rc = " << rc << endl;
printf("trc = %c\n", trc);
printf("itrc = %c\n", itrc);
printf("&c = %p\n", &c);
printf("&rc = %p\n", &rc);
cout << "&trc = " << &trc << endl;
cout << "&itrc = " << &itrc << endl;
return 0;
}
输出结果:
x = 1
&x = 0xbfcd055c
rx = 5
&rx = 0xbfcd055c
nrx = 5
&nrx = 0xbfcd055c
y = 10
*p = 10
p = 0xbfcd0560
c = a
rc = a
trc = d
itrc = d
&c = 0xbfcd055b
&rc = 0xbfcd055b
&trc = 0xbfcd0564
&itrc = 0xbfcd0564
2. 关于引用的疑问
问题: 引用与指针有什么关系?如何理解引用的本质就是指针常量?
-
指针是一个变量
- 指针的值为一个内存地址,不需要初始化,可以保存不同的地址;
- 通过指针可以访问对应内存地址中的值;
- 指针可以被
const修饰成为常量或者只读变量。
-
引用只是一个变量的新名字
- 对引用的操作(赋值,取地址等)都会传递到代表的变量上;
-
const引用使其代表的变量具有只读属性; - 引用必须在定义时初始化,之后无法代表其它变量。
从使用C++语言的角度来看:引用与指针没有任何的关系,引用是变量的新名字,操作引用就是操作对应的变量;
在C++编译器的角度来看:为支持新概念“引用”必须要一个有效的解决方案,在编译器内部,使用指针常量来实现“引用”,因此,“引用”在定义时必须初始化。
-
在工程项目开发中
- 在进行C++编程时,直接站在使用的角度看待引用,与指针毫无关系,引用就是变量的别名
- 在对C++代码进行调试分析时,一些特殊情况,可以考虑站在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};
int& array[] = {a, b, *pc}; // &array[1] - &array[0] = ? Expected ==> 4
// 在C语言中数组,数组是一片连续的存储空间,而此时的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++中不支持引用数组
3. 小结
- 指针是一个变量
- 引用是一个变量的新名字
- const引用能够生成新的只读变量
- 在编译器内部使用指针常量实现“引用”
- 编译时不能直接确定初始值的const标识符都是只读变量
声明:此文章仅是本人在学习狄泰学院《C++深度解析教程》所做的笔记,文章中包含狄泰软件资料内容,一切版权归狄泰软件所有!
实验环境:gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)