const 不再迷茫
博客地址:http://blog.csdn.net/jiangxinnju
github:https://github.com/jiangxincode
首先说明一下const在C和C++中的主要用法,被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。它可以修饰变量、函数的参数、返回值,甚至函数的定义体。
const修饰变量
const修饰变量通常用于定义符号常量。我们过去一般使用宏定义的方式定义符号常量,比如:
#define PI3.1415926
其实我们也可以使用const方式定义符号常量,下面的语句与上面宏定义的方式达到的效果相似。
const double PI3.1415926
那两者有什么区别呢?在使用宏定义的方式时,首先在预处理过程中将源程序中的常量名全部替换成对应的字面常量,然后对替换过的源程序进行编译。相比较之下const方式不涉及预处理过程,它只在编译工程中起作用。因为宏定义方式定义的符号常量没有类型,所以不能进行严格的类型检查,而const则可以,并且有些调试工具可以对const常量进行调试,而不能对宏常量进行调试。但这也不是说宏常量就比const常量差,比如你能够利用const常量实现下面的宏定义功能么?
#ifndefJIANGXIN_H
#defineJIANGXIN_H
#endef
而且由于历史原因,实际上使用宏常量的情况远远大于const常量,特别是在纯C编程环境中。不过在C++编程环境中,我还是推荐你使用const,因为这更加安全。同时时刻记住一句话,const常量作用与编译期,宏常量作用于预编译期,当你遇到一些令人迷惑的问题时想想这句话,或许能够有所收获。
现在举几个例子:
const int m = 0; //其实我们通常把const符号常量叫做const常量,以便和宏常量区分
typedef char * pStr; //新的类型pStr,代表一个指向char的指针类型。
char string[4] = "abc";
const char *p1 = string;//p1是一个指针,指向一个const
char类型
p1++; //正确,p1本身不是常量,它指向一个常量
const pStr p2 = string; //p2是一个常量指针,这个指针指向一个char类型变量
p2++; //错误,p2是一个常量指针
char *const p3 = string; //p3同p2相同,是一个常量指针
char const* p4 = string; //p4同p1相同,是一个指向const
char的指针,只能用于C中,在C++中只能使用const
char *p4 = string;
const修饰函数形参
函数形参主要包括传值型参数,传指针型参数,传引用型参数。
对于传指针和传引用型参数,如果我们怕在该函数中错误的改变实参的值,一般都会加上const来修饰形参。
对于传值型参数,我们一般不会使用const修饰,因为完全没有必要,你是不是用const,都不能改变实参的值,因为传值型形参是在栈中分配的,函数调用之后一定会销毁。例如:void
Fun(int n)和void Fun(const int n)没有任何区别,而且还是代码更加晦涩,所以不推荐。但是有一种情况需要考虑,如果你需要传递一个比较复杂的类类型,但是你又不需要改变该类的对象,这时你可以将传值改为传指针或者引用,同时用const修饰。这样的话就避免了构造临时对象的开销。比如加入A是一个很复杂的类类型,这是使用void
Fun(const A &a)要比void Fun(A a)效率更高。
用const修饰函数的返回值
函数的返回值与形参类似,也包括返回值类型,返回指针类型,返回引用类型。
对于返回值类型为指针或者引用的情况,如果我们不希望其被修改,可以使用const对返回值进行限定。此时该返回值const修饰的同类型const指针(返回值为指针)或者同类型的const变量(返回值为引用,且该值为基本类型或者定义了拷贝构造函数、拷贝赋值运算符的类型)。如对于:
const char * Fun(void);
如下语句将出现编译错误:
char *str = Fun();//cannotconvert from 'const char *' to 'char *';
正确的用法是:
const char *str= Fun();
如果返回值类型为值类型,由于函数会把返回值复制到外部函数的存储单元中,加const修饰没有任何价值,所以不要把函数int
Fun(void) 写成const int Fun(void)。但是在某些情况下将值类型改为引用类型或者指针类型可以提高效率,可用不用const就看你要不要改变它们了。
const修饰成员函数
const关键字可以放在函数声明的尾部,表示该类成员不修改对象。注意const只能修饰类的成员函数,不能修饰普通函数,无论是C还是C++。
const 不再迷茫的更多相关文章
- let和const的区别
es6语法中新增了 let和const 不再只是有var 1. let的用法 let是用来声明变量的,它和var的用法差不多,但是let所声明的变量只在它的代码块内有效,像for循环里用let会更好点 ...
- winform总结2> Action<> ,Action,func<>,委托相关的理解
1,他们是什么: Action 封装一个方法,该方法不具有参数并且不返回值. Action<> 封装一个方法,该方法具有最多16个参数并且不返回值. func<> 封装一个具有 ...
- 游记——noip2016
2016.11.18 (day 0) 呆在家. 悠闲地呆在家.. 明后天可能出现的错误: 1)没打freopen.打了ctime: 2)对拍程序忘记怎么写了...忘记随机化种子怎么写了: 3)不知道厕 ...
- 【转】一名大学生的PHP进阶之路
我是一名河南某职业学院的学生,比较喜欢PHP开发 的 工作,自己也曾经自学过php,but如果没有老师教还真是难以坚持啊,在这里给大家说一下寒假在麦子的学习感受,首先说麦子每一堂课程都给了特别详细的 ...
- [Android Pro] Android Support 包里究竟有什么
reference to : http://www.2cto.com/kf/201411/350928.html 随着 Android 5.0 Lollipop 的发布,Android 又为我们提供了 ...
- 报名|「OneAPM x DaoCloud」技术公开课:Docker性能监控!
如今,越来越多的公司开始 Docker 了,「三分之二的公司在尝试了 Docker 后最终使用了它」,也就是说 Docker 的转化率达到了 67%,同时转化时长也控制在 60 天内. 既然 Dock ...
- [Effective Modern C++] Item 1. Understand template type deduction - 了解模板类型推断
条款一 了解模板类型推断 基本情况 首先定义函数模板和函数调用的形式如下,在编译期间,编译器推断T和ParamType的类型,两者基本不相同,因为ParamType常常包含const.引用等修饰符 t ...
- EC读书笔记系列之14:条款26、27、28、29、30、31
条款26 尽可能延后变量定义式的出现时间(Lazy evaluation) 记住: ★尽可能延后变量定义式的出现.这样做可增加程序的清晰度并改善程序效率 ----------------------- ...
- 如何让HTML的编写更具结构性
首先声明,我不是搞技术的,很多词汇写的不够专业,但作为一枚菜鸟,我站在菜鸟的角度,来讲述我在学习技术的过程中所遇到的问题,和解决的方案. 入门HTML还算简单,无非是先写好固定的三对开闭标签结构:ht ...
随机推荐
- vs自带iis局域网调试
http://www.cnblogs.com/liluping860122/p/4685564.html
- WinForm窗体及其控件的自适应
3步骤: 1.在需要自适应的Form中实例化全局变量 AutoSizeFormClass.cs源码在下方 AutoSizeFormClass asc = new AutoSizeFormClass ...
- 在centos6.3用yum安装redis
一.centos默认的安装源在官方centos.org上,而redis在第三方的yum源里,所以无法安装,非官方的yum推荐用fedora的epel仓库.当然也可通过配置 /etc/yum.repos ...
- 【leetcode❤python】26. Remove Duplicates from Sorted Array
#-*- coding: UTF-8 -*-class Solution(object): def removeDuplicates(self, nums): "&quo ...
- CUBRID学习笔记 5 错误码
服务器错误码 AS Error Code Number CAS Error Code Error Message Note -1000 CAS_ER_DBMS "CUBRID DBMS Er ...
- python_way day16 JQuary
python_way day16 JQuery 封装dom js代码 jQuery(1.10,1.12-兼容性好,2.0.以后放弃了ie9以下) - 封装了Dom & JavaScript 查 ...
- Comware 架构理解
网络操作系统 首先什么是网络操作系统: 一种说法是:运行在路由器,网络交换机,防火墙上的特别的操作系统 另一种说法是:部署在局域网或者私有网络,允许网络中的多个计算机共享文件和打印机,因为现在的单机系 ...
- 作用域内优先级及this指针
函数声明>变量声明 作用域:顶部----------------------> 函数声明会覆盖变量声明,但不会覆盖变量赋值 this指针不是变量.当调用括号的左边不是引用类型而是其它类型, ...
- 10款Windows命令行工具
Windows下CMD不好用,远没有Linux,或者一些SSH工具用起来方便.其实Windows下,也有一些不错的工具替代CMD: 0.powercmd经过比较,我最终选择了这款,这里补充一下截图:
- php笔记[2]
strlen()函数获得字符窜的长度 读取文件:fgets(),fgetss()和fgetcsv() 读取整个文件:readfile(),fpassthru()和file() 读取一个字符:fgetc ...