C++在const用法
注意
- const对象默觉得文件的局部变量
在全局作用域里定义非const变量时,它在整个程序中都能够訪问。我们能够把一个非const变量定义在一个文件里,如果已经做了合适的声明,就能够在另外的文件里使用这个变量:


与其它变量不同,除非特别说明。在全局作用域声明的const变量是定义该对象的文件的局部变量。
此变量仅仅存在于那个文件里,不能被其它文件訪问。通过指定const变量为extern。就能够在整个程序中訪问const对象。


注意:非const变量默觉得extern。
要使const变量可以在其它文件里訪问,必须在文件里显式地指定它为extern。
------------- const指针、const引用、const引用形參 --------------------
【1】const修饰指针和引用
1. 术语“const引用”就是“指向const对象的引用”,习惯说成const引用与非const引用。
这点与指针不同,指针中“const指针”与“指向const对象的指针”是不同的。
2. 值得注意的是:const引用和指向const对象的指针二者有一个共同点:const引用既能够指向const对象又能够指向非const对象;指向const对象的指针亦是如此.
3. 关于const指针与指向const对象的指针,举一个非常easy样例
|
1
2
3
4
5
6
|
int constint*p1=&m; //指向const对象的指针:const修饰的是*p1, 即*p1的值是仅仅读的;可是p1这个指针是能够改动的。int const p2=&n; //const指针:const修饰的是p2, 即p2这个指针是仅仅读的;可是*p2的值是能够改动的。p1=&n; //p1的指针改动为变量n的地址,而这个地址就是p2,相当于p1=p2;*p2=3; //*p2的值改动为3。当然*p1的值也就是3printf("%d %d\n",*p1,*p2); |
【2】形參为const引用的优点
说到const,就不得不提const引用类型的形參,真正理解了const引用形參的优点,才发现它真是美妙的非常
简单总结一下。欢迎补充
a. 当实參的类型比較大时。复制开销非常大(形參初始化时),引用会“避免复制”。
(这在传递类对象时比較经常使用)
b. “避免改动实參”。当使用引用时,假设调用者希望仅仅使用实參并不改动实參。则const能够避免使用该引用改动实參
c. 相比非const引用形參,更具有用性:形參能够使用const对象初始化,可使用字面值或右值表达式的实參来初始化
以下各给一演示样例
|
1
2
3
4
5
6
7
8
|
a. voidsearch(constvector<int>b. 同a例。可避免对实參做出改动c. 例如以下函数,调用时void "hello");// Error 实參为字面值常量void const "hello");// OK再如void int & v); 调用: search(v1+v2); // Error 实參是一个右值。无法给引用赋值(须要左值)void const & v); 调用: search(v1+v2); // OK |
---------------const 在类中----------------------------------------
一般来讲。使用const修饰函数,则函数一定是类成员函数。
【1】const对象仅仅能调用const成员函数 非const对象能够调用const成员函数
解释:不能将指向const对象的指针赋值给非const对象指针,而同意将非const对象指针赋值给指向const对象的指针。
为什么这样解释?这源自于调用成员函数时发生的事情:
调用成员函数时会发生的事情:将调用对象与函数绑定,即将成员函数隐含的形參this初始化为调用对象的地址。
因此,const对象传递的实參地址为const class * const this。而非const成员函数被调用时还是使用了class *const this的形參接收,结果就是把指向const对象的指针赋给非const对象的指针,这是不同意的。所以const对象仅仅能调用const成员函数。后者同理,非const对象在调用const成员函数时实质上是将非const对象的指针(实參)赋值给了const对象指针(形參),而这又是能够的。故非const对象能够调用const成员函数。
【2】const成员变量不能被改动,且必须在初始化列表中赋值。
const成员函数不能改变成员变量, 且不能调用非const成员函数(即不可有改变值的企图)
相反,非const成员函数当然能够调用const成员函数
【3】const成员函数的返回值:值类型 & const引用类型 (不可返回非const引用)
|
1
2
3
4
5
6
7
8
9
10
11
|
example.classVec{private: vector<string> textVec;public: conststring & text_line(size_tlineNum)const { returntextVec.at(lineNum-1); }}; |
假设成员函数为const,则对象调用该常函数传递this时已经变成了const对象,假设函数写成例如以下形式
|
1
2
3
4
|
string & text_line(size_tlineNum)const{ returntextVec.at(lineNum-1);} |
则编译会报错:不能将const string 转化为 string &,由于此时相当于将一个非const引用指向了一个const类型变量。故要返回引用就必须是const引用。
------------返回值类型---
当然还有其它的写法,即让函数返回值为值类型,即
|
1
2
3
4
|
string text_line(size_tlineNum)const{ returntextVec.at(lineNum-1);} |
此时实际上是做了一个内存拷贝,由于string是类类型,有人会问,那这样不是相当于一个const对象赋值给非const对象吗?
对于上述函数,实际是调用了string的拷贝构造,并且拷贝构造的參数便是const string类型。这里又涉及到const类型作參数的问题。上面已讲
对于函数的返回值为值类型,无非就两种,一种是普通的内置类型。进行赋值操作;一种是类类型,调用拷贝构造进行内存拷贝。例如以下:
|
1
2
3
4
|
constinta = 9;int int // error) // 赋值constset<int> s;set<int> ss = s; // 内存拷贝 |
所以我们要注意:
不能够将const对象指针或引用赋值给非const对象的指针和引用。可是能够将const对象初始化给非const对象;
const与非const在对象层次(not引用或指针层次)上的互相赋值是同意的。可逆的;就像
|
1
2
3
|
constinta = 9;int constintaaa = aa; |
-------------------const与重载---------------------------------------
基于const重载的情况有两种,一种是基于函数形參类型是否为const的重载;一种是基于类成员函数是否为const的重载
【1】 基于函数形參类型是否为const的重载
当且仅当形參为引用或指针类型时。形參是否为const才有影响
-----引用类型----
可基于函数的引用形參是指向const对象还是指向非const对象,实现重载,示比例如以下:
|
1
2
3
4
5
6
|
A: voidsearch(Student &);B: voidsearch(constStudent &);constStudent a;Student b;search(a); // 调用Bsearch(b); // 调用A |
注:依据上面讲的我们知道,假设形參是普通引用,则不能将const对象传递给该形參。
假设传递的是非const对象。按上面提到的,这两种函数都是可行的,由于非const对象既可用于初始化const引用,也可初始化非const引用。那么没有二义性么?
这就是编译器在调用函数时遵循的原则首先是“精确匹配”,我们知道,将const引用初始化为非const对象须要隐式转换的。所以不符合精确匹配,故调用A。
-----指针类型----
基于指针形參的const重载与引用是一样的。
仅仅是有一个问题要注意:
上面术语说到const引用就是指向const对象的引用,指针则差别于const指针和指向const对象的指针。
所以要注意:不能基于指针本身是否为const来重载函数
|
1
2
3
4
|
void int * ptr);void int * const ptr);// 这不能实现重载,指针本身是否const并不会带来差别// 在函数调用时,形參都复制了指针的值 |
【2】 基于类成员函数是否为const的重载
在类中,基于成员函数是否为const,可重载一个成员函数,例如以下
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
classVec{private: vector<string> textVec;public: conststring & text_line(size_tlineNum)const { returntextVec.at(lineNum-1); } string & text_line(size_tlineNum) { returntextVec.at(lineNum-1); }}; |
版权声明:本文博客原创文章,博客,未经同意,不得转载。
C++在const用法的更多相关文章
- c++ const用法小结
const用法 1,定义全局变量的内存分配问题 #define Pi_1 3.14 //使用#define宏 const double Pi_2 = 3.14 //使用const ...
- const用法
一.const作用 二.const用法 1.修饰一般常量 修饰符const可以用在类型说明符前,也可以用在类型说明符后. 例如: ; ; 2.修饰常数组 修饰符const可以用在类型说明符前,也 ...
- 【转】话说C语言const用法
原文:话说C语言const用法 const在C语言中算是一个比较新的描述符,我们称之为常量修饰符,意即其所修饰的对象为常量(immutable). 我们来分情况看语法上它该如何被使用. 1.函数体内修 ...
- static 与单例模式、auto_ptr与单例模式、const 用法小结、mutable修饰符
一.static 与单例模式 单例模式也就是简单的一种设计模式,它需要: 保证一个类只有一个实例,并提供一个全局访问点 禁止拷贝 C++ Code 1 2 3 4 5 6 7 8 9 10 11 ...
- const用法详解(转)
http://www.cnblogs.com/StudyRush/archive/2010/10/06/1844690.html 面向对象是C++的重要特性. 但是c++在c的基础上新增加的几点优化也 ...
- C++之常指针,指针常量,函数指针,const用法总结
1.const char *p,char const *p,char * const p 对于C++而言,没有const * 修饰符,所以,const只可以修饰类型或者变量名.因而const char ...
- C++的那些事:const用法面面观
一.const是什么 在 C/C++ 语言中,const关键字是一种修饰符.所谓“修饰符”,就是在编译器进行编译的过程中,给编译器一些“要求”或“提示”,但修饰符本身,并不产生任何实际代码.就 con ...
- 【三支火把】---C语言const用法总结
C语言关键字const相信对于不少C语言新手是既陌生又熟悉的,好像经常见,但是却不知道为何用,怎么用?学习至此,总结一下const的用法,使用程序来帮助你理解该关键字,希望能帮到像我一样的新手. 我看 ...
- typedef,static,const用法
一.typedef主要功能是定义一个已存在类型的别名,但是和宏并存 宏与typedef区别 1.宏定义只是简单的字符串替换 2.typedef定义的类型是类型的别名,typedef后面是一个整体声明, ...
- C++中const用法详解
本文主要内容来自CSDN论坛: http://bbs.csdn.net/topics/310007610 我做了下面几点补充. 补充: 1. 用const声明全局变量时, 该变量仅在本文件内可见, 类 ...
随机推荐
- T-SQL开发——ID处理篇
原文:T-SQL开发--ID处理篇 数据库自增ID功能中Identity.Timestamp.Uniqueidentifier的区别: 问题现象: 一般序号的产生,对于一般程序员而言,都是使用T-SQ ...
- T-SQL问题解决集锦——数据加解密
原文:T-SQL问题解决集锦--数据加解密 以下代码已经在SQLServer2008上的示例数据库测试通过 问题一:如何为数据进行加密与解密,避免使用者窃取机密数据? 对于一些敏感数据,如密码.卡号, ...
- ZendFramework2学习笔记 json和ajax
单程: View服务寄存器ViewJsonStrategy之后,有可能直接在控制器action是使用JsonViewModel输出json的数据. 注冊ViewJsonStrategy: //modu ...
- WPF学习(4)逻辑树和可视树
前面几节说了一些WPF的基础,包括XAML和布局等.在接下来的几节,我们来说说WPF的核心概念,包括逻辑树和可视树.依赖对象和依赖属性.路由事件.命令这几个部分.本节介绍下逻辑树(Logical Tr ...
- Windows命令行命令集锦
原文:Windows命令行命令集锦 转自:http://www.me2wg.com/bbs/forum.php?mod=viewthread&tid=15830 winver--------- ...
- 对于超大型SQL SERVER数据库执行DBCC操作
原文:对于超大型SQL SERVER数据库执行DBCC操作 对于数据库维护,主要使用DBCC CHECKDB来实现,以下是对大型数据库的使用说明,小型数据库一般直接使用就可以了: 1.2008(200 ...
- css3 menu 手机菜单3
首先看一下效果图; 效果1,主要是 scale(0) -->scale(1px);opacity:0;—>opacity: 1; 然后递归延迟 怕麻烦也可以自己写个for循环 .five ...
- [6] 算法路 - 双向冒泡排序的Shaker
Shaker序列 –算法 1. 气泡排序的双向进行,先让气泡排序由左向右进行.再来让气泡排序由右往左进行,如此完毕一次排序的动作 2. 使用left与right两个旗标来记录左右两端已排序的元素位置. ...
- jquery的智能提示控件
福利到~分享一个基于jquery的智能提示控件intellSeach.js 一.需求 我们经常会遇到[站内搜索]的需求,为了提高用户体验,我们希望能做到像百度那样的即时智能提示.例如:某公司人事管 ...
- Matlab与.NET基于类型安全的接口混合编程入门
原文:[原创]Matlab与.NET基于类型安全的接口混合编程入门 如果这些文章对你有用,有帮助,期待更多开源组件介绍,请不要吝啬手中的鼠标. [原创分享]Matlab.NET混编调用Figure窗体 ...