C++解析(9):关于const和引用的疑问
0.目录
1.关于const的疑问
2.关于引用的疑问
- 2.1 引用与指针
- 2.2 从C++语言与C++编译器角度看引用
- 2.3 从工程项目开发看引用
3.小结
1.关于const的疑问
const什么时候为只读变量?什么时候是常量?
const常量的判别准则:
- 只有用字面量初始化的const常量才会进入符号表
- 使用其它变量初始化的const常量仍然是只读变量
- 被volatile修饰的const常量不会进入符号表
(volatile代表所声明的标识符是易变的,是可能发生变化的,只不过这个可能性也许不在当前编译的文件当中,这个使得当前标识符发生变化的可能性是发生在外部的,外部就相当于是其它文件当中,比如多线程、中断等等。volatile既然代表易变的,那么每次访问volatile所修饰的标识符时应该到内存里面去直接读取。这就意味着被volatile所修饰的标识符不可能进入符号表,也就是说当volatile和const同时修饰一个标识符的时候,得到的仅仅是一个只读变量,const在这里的意义仅仅是说明在当前的文件当中或者说当前的作用域当中,volatile和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;
}
运行结果:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
x = 1
rx = 5
nrx = 5
&x = 0x7ffd8a40b3cc
&rx = 0x7ffd8a40b3cc
&nrx = 0x7ffd8a40b3cc
使用volatile,是真正的常量吗?
证明在编译期间不能直接确定初始值的const标识符,都被作为只读变量处理。
#include <stdio.h>
int main()
{
volatile const int y = 2;
int* p = const_cast<int*>(&y);
*p = 6;
printf("y = %d\n", y);
printf("p = %p\n", p);
const int z = y;
p = const_cast<int*>(&z);
*p = 7;
printf("z = %d\n", z);
printf("p = %p\n", p);
return 0;
}
运行结果:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
y = 6
p = 0x7fff2eab9144
z = 7
p = 0x7fff2eab9140
最后验证const引用的类型与初始化变量的类型相同和不同的情况:
#include <stdio.h>
int main()
{
char c = 'c';
char& rc = c;
const int& trc = c;
rc = 'a';
printf("c = %c\n", c);
printf("rc = %c\n", rc);
printf("trc = %c\n", trc);
return 0;
}
运行结果:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
c = a
rc = a
trc = c
2.关于引用的疑问
2.1 引用与指针
引用与指针有什么关系?如何理解“引用的本质就是指针常量”?
指针是一个变量:
- 值为一个内存地址,不需要初始化,可以保存不同的地址
- 通过指针可以访问对应内存地址中的值
- 指针可以被const修饰成为常量或者只读变量
引用只是一个变量的新名字:
- 对引用的操作(赋值,取地址等)都会传递到代表的变量上
- const引用使其代表的变量具有只读属性
- 引用必须在定义时初始化,之后无法代表其它变量
2.2 从C++语言与C++编译器角度看引用
从使用C++语言的角度来看:
- 引用与指针没有任何的关系
- 引用是变量的新名字,操作引用就是操作对应的变量
从C++编译器的角度来看:
- 为了支持新概念“引用”必须要一个有效的解决方案
- 在编译器内部,使用指针常量来实现“引用”
- 因此“引用”在定义时必须初始化
2.3 从工程项目开发看引用
在工程项目开发中:
- 当进行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
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;
}
运行结果为:
[root@bogon Desktop]# g++ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:17: error: declaration of ‘array’ as array of references
原因:引用数组破坏了数组地址空间的连续性!!!
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};
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;
}
运行结果为:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
&sv.x = 0x600b14
&sv.y = 0x7ffc32798de4
&sv.z = 0x23be010
3.小结
- 指针是一个变量
- 引用是一个变量的新名字
- const引用能够生成新的只读变量
- 在编译器内部使用指针常量实现“引用”
- 编译时不能直接确定初始值的const标识符都是只读变量
C++解析(9):关于const和引用的疑问的更多相关文章
- C++ Prime:const的引用
可以把引用绑定到const对象上,就像绑定到其他对象上一样,我们称之为对常量的引用.与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象: ; const int &r1 = ci; ...
- const 相关知识 const和指针、const和引用
以前老是对const概念不清不楚,今天算是好好做个笔记总结一下.以下内容包括1)常量指针(指针本身是常量),2)指针常量(指针指向的是常量对象),3)常量引用,4)const成员函数. 常量指针,指针 ...
- [转]为什么复制构造函数的参数需要加const和引用
[转]为什么复制构造函数的参数需要加const和引用 一.引言 1.0在解答这个问题之前,我们先跑个小程序,看下调用关系. #include <iostream> using namesp ...
- const的引用
const的引用 对常量的引用:把引用绑定到const对象上,就像绑定到其他对象上一样,不能被用作修改它所绑定的对象: ; const int &r1 = ci;//正确:引用及其对应的对象都 ...
- 创建在类路径资源[applicationcontext]中定义名为“工厂”的bean时出错。:在设置bean属性“dataSource”时,无法解析对bean“dataSource”的引用;嵌套异常是org.springframe .beans.factory。BeanCreationException:创建名为“数据源”的bean时出错,该名称是在类路径资源[applicationcontext
控制台报错: 创建在类路径资源[applicationcontext]中定义名为“工厂”的bean时出错.:在设置bean属性“dataSource”时,无法解析对bean“dataSource”的引 ...
- 【C++编程基础】(1)—— 函数原型声明、函数模板、引用、const 常引用、const 常量指针
一.函数原型声明: 1.函数声明告诉编译器函数的名称,和如何调用函数(返回类型和参数):函数定义提供了函数的实际主体. 2.强制性的:在C++中,如果函数调用的位置在函数定义之前,则要求在函数调用之前 ...
- C++ 中的 const、引用和指针的深入分析
1,关于 const 的疑问: 1,const 什么时候为只读变量,什么时候是常量: 1,const 从 C 到 C++ 进化的过程中得到了升级,const 在 C++ 中不仅仅像在 C 中声明一个只 ...
- const、引用与指针
前提 我们忽略掉了相同类型是否可以赋值的情况(我到现在的学习里都还可以相互赋值),以及类型兼容的情况.只考虑const.&.*等修饰符带来的影响 类型兼容: 强制类型转换 基类与子类间的兼容 ...
- C++初阶(命名空间+缺省参数+const总结+引用总结+内联函数+auto关键字)
命名空间 概述 在C/C++中,变量.函数和后面要学到的类都是大量存在的,这些变量.函数和类的名称将都存在于全局作用域中,可能会导致很多冲突.使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲 ...
随机推荐
- 【Todo】找出共同好友 & Spark & Hadoop面试题
找了这篇文章看了一下面试题<Spark 和hadoop的一些面试题(准备)> http://blog.csdn.net/qiezikuaichuan/article/details/515 ...
- centos7.5yum安装mysql(官方yum源比较慢)
mysql的部署 查看Linux发行版本 cat /etc/redhat-release 下载MySQL官方的Yum Repository wget -i http://dev.mysql.com/g ...
- 【转载】C/C++杂记:深入理解数据成员指针、函数成员指针
原文:C/C++杂记:深入理解数据成员指针.函数成员指针 1. 数据成员指针 对于普通指针变量来说,其值是它所指向的地址,0表示空指针.而对于数据成员指针变量来说,其值是数据成员所在地址相对于对象起始 ...
- Numpy入门笔记第三天
__TITLE__ = "利用Numpy进行历史股价分析" __DATASOURCE__ = "ATAGURU" # CSV文件读取 import numpy ...
- 福利,一张图看懂IT售前工程师修炼之道
职场中的新人如何自我定位? 如何深刻理解IT售前这个职位? 如何从IT售前菜鸟成长为IT售前专家? 推荐这本书<IT售前工程师修炼之道> 本书精华内容 售前的重要性 售前要有逻辑能力 售前 ...
- Nginx连载
一. nginx变量(用户变量.内建变量) 用户变量 又称用户自定义变量 Nginx用户变量的可见范围是整个配置文件,甚至可以跨越不通虚拟主机的server配置,但是变量适用范围是不可以跨越自己的容器 ...
- LeetCode 48. Rotate Image (C++)
题目: You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwis ...
- Scrum立会报告+燃尽图(十一月十八日总第二十六次):功能开发与讨论贡献分配规则
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2284 项目地址:https://git.coding.net/zhang ...
- ACM-ICPC 2018 沈阳赛区网络预赛
Supreme Number 1000ms 131072K A prime number (or a prime) is a natural number greater than 111 tha ...
- iOS- Autolayout自动布局
1.前言 •在iOS程序中,大部分视图控制器都包含了大量的代码用于设置UI布局,设置控件的水平或垂直位置,以确保组件在不同版本的iOS中都能得到合理的布局 •甚至有些程序员希望在不同的设备使用相同的视 ...