C++ 中的 const、引用和指针的深入分析
1,关于 const 的疑问:
1,const 什么时候为只读变量,什么时候是常量;
1,const 从 C 到 C++ 进化的过程中得到了升级,const 在 C++ 中不仅仅像在 C 中声明一个只读变量,其在 C++ 中完全可以得到一个常量;
2,const 常量的判别准则:
1,只有用字面量初始化的 const 常量才会进入符号表;
1,这里是字面量初始化 const 常量,不是 const 常引用;
2,得到了真正意义上的常量;
2,使用其他变量初始化的 const 常量仍然是只读变量;
1,编译器在编译期间不可能知道变量初始化时候的值;
2,得到只读变量;
3,被 volatile 修饰的 const 常量不会进入符号表;
1,volatile 表示声明的标识符是易变的;
2,这个可能的易变性也许不在当前编译的文件中,发生在外部;
3,外部相当于在其它文件中,比如多线程、中断等;
4,每次访问 volatile 修饰的标识符时,因为是易变的,所以应该到内存中直接读取;
5,意味着被 volatile 修饰的标识符不可能进入符号表;
6,意味着当 volatile 和 const 同时修饰一个标识符时,得到的是只读变量,不可能进入符号表;
7,const 此时的意义说明在当前的文件或者当前的作用域当中,volatile 和 const 一起修饰的标识符不能出现在赋值符号的左边;
(4),在编译期间不能直接确定初始值的 const 标识符,都被作为只读变量处理;
3,const 引用的类型与初始化变量的类型:
1,相同:初始化变量成为只读变量;
2,不同:生成一个新的只读变量;
4,const 典型问题分析编程实验:
1,main.cpp 文件:
#include <stdio.h> int main()
{
const int x = ;//直接得到值,进入符号表,但是还是会为 x 分配空间,只不过这个空间 x 没有用而已;
const int& rx = x;//rx代表只读变量,这个变量是编译器为x分配而没有使用的空间;引用代表变量的别名,而变量代表一段内存空间的别名,所以引用代表一段内存空间的别名; int& nrx = const_cast<int&>(rx); //消除 rx只读属性,和rx 代表的内存空间相同; nrx = ; 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); volatile const int y = ; // 只读变量;
int* p = const_cast<int*>(&y); //y被 const修饰,取到的地址也有 const 属性,这里将地址只读属性去掉; *p = ; printf("y = %d\n", y);
printf("p = %p\n", p); const int z = y; // y 是变量,得到只读变量; p = const_cast<int*>(&z); *p = ; printf("z = %d\n", z);
printf("p = %p\n", p); char c = 'c';
char& rc = c;
const int& trc = c; // char 类型默认转换为 int;const 引用初始化类型不同,将得到新的只读变量,所以改变 rc 和 trc 没有丝毫关系; 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 ;
}
2,输出结果:
x = // 进入符号表,编译期间就是 1;
rx =
nrx =
&x = 0xbfb1a708//为const修饰的标识符分配空间,通过指针或引用使用;
&rx = 0xbfb1a708
&nrx = 0xbfb1a708
y =
p = 0xbfb1a6fc
z =
p = 0xbfb1a6f4
c = a
rc = a
trc = c // 原始的赋值结果;
&c = 0xbfd1242f
&rc = 0xbfd1242f
&trc = 0xbfd12408 // 新开辟的空间;
5,关于引用的疑问:
1,引用与指针有什么关系,如何理解“引用的本质就是指针常量”;
6,指针和引用分析:
1,指针是一个变量:
1,值为一个内存地址,不需要初始化,可以保存不同的地址;
2,通过指针可以访问对应内存地址中的值;
3,指针可以被 const 修饰成为常量或者只读变量;
2,引用只是一个变量的新名字:
1,对引用的操作(赋值,取地址等)都会传递到代表的变量上;
1,新名字是一段内存空间的代号;
2,引用是给已经存在的合法内存空间一个新的代号;
2,const 引用使其代表的变量具有只读属性;
3,引用必须在定义时初始化,之后无法代表其它变量;
1,身份证号代表一个人,不能复用;
2,一个车牌号就代表一个车,不能复用;
3,因为是指针常量,所以不能代表其它变量;
7,从 C++ 不同角度分析引用:
1,从使用 C++ 语言的角度来看:
1,引用与指针没有任何的关系;
2,引用是变量的新名字,操作引用就是操作对应的变量;
2,从 C++ 编译器的角度来看:
1,为了支持新概念,“引用”必须要一个有效的解决方案;
2,在编译器内部,使用指针常量来实现“引用”;
3,因此“引用”在定义时必须初始化;
8,在工程项目开发中:
1,当进行 C++ 编程时,直接站在使用的角度看待引用,与指针毫无关系,引用就是变量的别名;
2,当对 C++ 代码进行调试分析时,一些特殊情况,可以考虑站在 C++ 编译器角度看待引用;
3,下面代码正确吗?
int a = ;
int b = ;
int* pc = new int();
int& array[] = [a, b, *pc];
9,引用典型问题分析编程实验:
1,main.cpp 文件:
#include <stdio.h> int a = ; struct SV
{
int& x;
int& y;
int& z;
}; int main()
{
int b = ;
int* pc = new int();
SV sv = {a, b, *pc}; // 结构体中的每个元素是引用就可以;
// int& array[] = {a, b, *pc}; //数组中的每个元素是引用就不可以;error: declaration of ‘array’ as array of references; C++ 天生要支持 C 语言,C 语言中数组中的每个元素在内存中是顺序存放的,地址是递增的,所以在 C++ 中也要兼容这个特性,而在 C++ 中唯有引用数组破快了这个特性,所以说 C++ 中不支持引用数组;&array[1] - &array[0] = ? Expected ==> 4; printf("&sv.x = %p\n", &sv.x);
printf("&sv.y = %p\n", &sv.y);
printf("&sv.z = %p\n", &sv.z); delete pc; return ;
}
2,输出结果:
&sv.x = 0x804a020
&sv.y = 0xbffe92bc
&sv.z = 0x9f97008
3,在开发中遇到奇怪的 bug,要站在编译器的角度考虑问题;
10,小结:
1,指针是一个变量;
2,引用是一个变量的新名字;
3,const 引用能够生成新的只读变量;
4,在编译器内部使用指针常量实现“引用”;
1,C++ 中为了兼容 C 语言中的所有特性,放弃了引用数组,这样会使得相邻元素的地址之差不是期望的;
5,编译时不能直接确定初始值的 const 标识符都是只读变量;
C++ 中的 const、引用和指针的深入分析的更多相关文章
- c++中的引用与指针的区别
http://blog.csdn.net/lyd_253261362/article/details/4323691 c++中的引用与指针的区别 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存 ...
- 不可或缺 Windows Native (18) - C++: this 指针, 对象数组, 对象和指针, const 对象, const 指针和指向 const 对象的指针, const 对象的引用
[源码下载] 不可或缺 Windows Native (18) - C++: this 指针, 对象数组, 对象和指针, const 对象, const 指针和指向 const 对象的指针, con ...
- C++中引用与指针的区别(详细介绍)
C++中引用与指针的区别(详细介绍) C++中的引用与指针的区别 指向不同类型的指针的区别在于指针类型可以知道编译器解释某个特定地址(指针指向的地址)中的内存内容及大小,而void*指针则只表示一 ...
- C++ 中引用与指针的区别
1.引用只是变量的一个别名,并不占用内存空间,而指针是一个变量,里面保存着被指向的变量在内存中的地址: 2 引用只能在定义时被初始化一次,之后不可变,而指针可变: 3 引用没有 const,指针有 c ...
- [ZZ]C++中,引用和指针的区别
(1) 引用总是指向一个对象,没有所谓的 null reference .所有当有可能指向一个对象也由可能不指向对象则必须使用 指针. 由于C++ 要求 reference 总是指向一个对象所以 re ...
- 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针
您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. ...
- c++中的const参数,const变量,const指针,const对象,以及const成员函数
const 是constant 的缩写,“恒定不变”的意思.被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性.所以很多C++程序设计书籍建议:“Use const whe ...
- C、C++中引用与指针的区别
1:引用的和指针在概念上的区别 引用是变量的别名,例如 int m; int &n=m; 引用作为一个别名.它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用 ...
- 【C++】C++中的引用与指针
想必大家对C++中的指针都有所了解,但是什么是引用呢?C++11标准引入了“引用”的新功能. 引用 引用(reference):给对象起了另外一个名字,引用类型引用(refers to)另外一种类型, ...
随机推荐
- NGUI的拖拽和放下功能的制作,简易背包系统功能(drag and drop item)
一我们添加sprite,给sprite添加背景图片和添加box collider,但是drag and drop item在attach中是找不到的只能在add component中查找添加,如下图: ...
- Css3-颜色 color
一.颜色 RGBA RGB是一种色彩标准,是由红(R).绿(G).蓝(B)的变化以及相互叠加来得到各式各样的颜色.RGBA是在RGB的基础上增加了控制alpha透明度的参数. 语法:color:rgb ...
- Kvm --05 密码保护:Kvm管理之WebVirtMgr
目录 密码保护:Kvm管理之WebVirtMgr 1. 前言 2. 特点 3. 功能 4. 部署 1).安装相关依赖 2).安装Python需求环境 3).配置Nginx 4). 远程连接 5).更新 ...
- easyapi
create database easyrec; #为easyrec初始化用户名跟密码grant index, create, select, insert, update, drop, delete ...
- JavaScript判断对象是否相等
实现一. var obj = {a:'a'},obj1 = {b:'b'},obj2 = {a:'a'};就是使用JSON.stringify()先把对象转化成字符串,这样就可以啦 console.l ...
- cassandra集群
cassandra是分布式数据库属于nosql,用于处理大量商用服务器上的大量数据,提供高可用性,无单点故障. Cassandra在其节点之间具有对等分布式系统,并且数据分布在集群中的所有节点之间. ...
- 如何使用WidsMob Montage—蒙太奇制作有趣的动物照片?
今天,越来越多的人有宠物.根据最近的一项调查,超过六成的美国人在家中至少有一只宠物.这些宠物不是动物,而是家庭成员.因此,有趣的动物照片成为社交媒体上的热门话题是有道理的.当您打开朋友圈或短视频APP ...
- 【leetcode】1007. Minimum Domino Rotations For Equal Row
题目如下: In a row of dominoes, A[i] and B[i] represent the top and bottom halves of the i-th domino. ( ...
- Delphi 运行后错误提示“无效的授权说明”
Delphi 运行后错误提示“无效的授权说明” 一般情况是:数据库的连接出现了问题. 解决方法:检查加载数据库是否正常,能否正常连接.
- boost asio scalability and multithreading
A library such as Boost.Asio is typically used to achieve greater efficiency. With no need to wait f ...