c++中const使用详解
const在c++中是一个关键字,它限定一个变量不允许被改变。使用const在一定程度上可以提高程序的安全性和可靠性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助。
和const相反的是mutable,mutable也是一个关键字,它的作用刚好和const相反,是说明这个变量可以被改变,即使是在被const限定的类的成员函数里面。
一:const和一般的变量相结合。
int const a = 10,与 const int a =10 这两种写法都是正确的,也是表达同一个意思。说明变量a不能不修改,这种用法大家都知道,所以不用多说。需要说明的是:const int 与int是两种不同的类型,之间不可相互转换。
用const定义的变量 如果不去引用它 这个变量只存在符号表中,但如果你引用它了 它就会在内存中分配一个临时存储区
const int a=1; //没有引用前,内存不分配变量空间,只存在符号表里
int &b=const_cast<int&>(a); //b是a的引用,即a,b指向同一个地址
b=2; //临时存储区里的值发生变化
cout<<&b<<":"<<*(&b)<<endl; //b的地址里的值 ,肯定是2了
cout<<&a<<":"<<*(&a)<<endl; //a仅仅存储在符号表里,值不能改变还是1,但你要调用他的地址(引用)就是临时分配的那个存储区了,即b的地址,这里&a==&b,但是*(&a)!=*(&b).从语法上看,这个不合理啊,相同地址里的值却不相同!这可能是编译器优化的结果,*(&a)编译期可能把它又化成a!
二:const和指针结合。
int * const a = new int[10];//说明a不能被更改,被看做一个常量,在定义的时候就要被初始化,如果在别的地方这样写 : a = new int,那么编辑器将要报错。
const int *a;//说明a指向的空间是不可更改的,而a本身并不是一个常量,所以在定义的时候可以不初始化,int b[2] ;a = b;如果这样写a[0] = 3;那么编译器同样会报错。
int const *a ;//这种写法和上面的是同一个意思。
const int * const a ;//这种写法说明不当a是不可改变的,而且a指向的空间也是不可改写的。
参考《Effective c++》Item21上的做法,如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。
三:const修饰函数的参数或者返回值,或者函数本身。
1,const修饰函数的参数,这个时候说明被修饰的那个参数是不可更改的。通常是参数为指针或者引用的情况,为了保证远指针指向的内容,或者原引用不可被更改。void func(const *a),void func(const &a)那在函数体内a的内容将不可被修改,如果是类的实例,那么a对象的成员变量将是不可被修改的,而且只能调用被const修饰的成员函数(这一点要值得注意)
原因如下:
如果返回值为某个对象为const(const A test = A 实例)或某个对象的引用为const(const A& test = A实例),则返回值具有const属性,则返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到eg:
class Test
{
public:
Test(Test &t)//拷贝构造函数
{
cout<<"copy construction"<<endl;
}
Test(const Test &t)//重载拷贝构造函数
{
cout <<"copy construction const "<<endl;
}
public :
Test()
{
}
void print()
{
cout<<"print"<<endl;
}
void print() const
{
cout<<"const Print"<<endl;
}
const Test &operator =(const Test&t)//运算符重载等号
{
cout<<"operator="<<endl;
return *this;
}
const Test &operator +(const Test &t1)//运算符重载加号
{
cout <<"Operator +"<<endl;
return *this;
}
};
void main()
{
Test a;
Test b;
Test c = a + b;//调用const Test &operator =(const Test&t)//
(a+b).print();//因为重载+号返回的是const类型的对象,而const类型的对象只能调用const函数,所以调用了void print()const 函数,而不是void print()函数
c.print();
}运行的结果Operator +
copy construction const
Operator +
const Print
这个列子虽很短,很简单,但是里面的很多东西都值得深思!
3.函数本身就是用const修饰的。这个时候函数只能是类的成员函数,如果这样写void Test () const;那么编译器将会提示非成员函数上不允许修饰符.所以这只是只对于类的成员函数而言的。
void Test::print () const;这样的声明说明print函数体内不可以改变改类的成员变量,但是用mutable修饰的成员变量可以被改变的(这也是mutable关键字的典型的用法)!
四 使用const的一些建议
1 要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;
2 要避免最一般的赋值操作错误,如将const变量赋值
3 在参数中使用const应该使用引用或指针,而不是一般的对象实例,原因同上;
4 const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;
5 不要轻易的将函数的返回值类型定为const;
6除了重载操作符外一般不要将返回值类型定为对某个对象的const引用;
ps:被const修饰的对象(对象是不可改变的),只能调用被const修饰的成员函数,
c++中const使用详解的更多相关文章
- C++中const用法详解
本文主要内容来自CSDN论坛: http://bbs.csdn.net/topics/310007610 我做了下面几点补充. 补充: 1. 用const声明全局变量时, 该变量仅在本文件内可见, 类 ...
- (转) C/C++中const关键字详解
文章转自 http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777416.html 为什么使用const?采用符号常量写出的代码更容易维 ...
- C++中const关键字详解
1.什么是const? const意味着是常量类型,被const修饰的变量或对象是不能被修改和更新的,当然在某些情况下,我们可以偷梁换柱的改变它. 2.为什么要引入const? 最初的目的是为了取代预 ...
- 【转载】C/C++中extern关键字详解
1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...
- C++初学者 const使用详解
关于C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,参考了康建东兄的const使用详解一文,对其中进行了一些补充,写下了本文. 1. const常量 如: cons ...
- C++中的STL中map用法详解(转)
原文地址: https://www.cnblogs.com/fnlingnzb-learner/p/5833051.html C++中的STL中map用法详解 Map是STL的一个关联容器,它提供 ...
- const用法详解(转)
http://www.cnblogs.com/StudyRush/archive/2010/10/06/1844690.html 面向对象是C++的重要特性. 但是c++在c的基础上新增加的几点优化也 ...
- ALSA声卡驱动中的DAPM详解之七:dapm事件机制(dapm event)
前面的六篇文章,我们已经讨论了dapm关于动态电源管理的有关知识,包括widget的创建和初始化,widget之间的连接以及widget的上下电顺序等等.本章我们准备讨论dapm框架中的另一个机制:事 ...
- ALSA声卡驱动中的DAPM详解之六:精髓所在,牵一发而动全身
设计dapm的主要目的之一,就是希望声卡上的各种部件的电源按需分配,需要的就上电,不需要的就下电,使得整个音频系统总是处于最小的耗电状态,最主要的就是,这一切对用户空间的应用程序是透明的,也就是说,用 ...
随机推荐
- Linux系统各发行版镜像下载(持续更新)
Linux系统各发行版镜像下载(持续更新) http://www.linuxidc.com/Linux/2007-09/7399.htm Linux系统各发行版镜像下载(2014年10月更新),如果直 ...
- Queue类
1.LinkedBlockingQueue:基于链接节点的可选限定的blocking queue . 这个队列排列元素FIFO(先进先出). 队列的头部是队列中最长的元素. 队列的尾部是队列中最短时间 ...
- C json实战引擎 三 , 最后实现部分辅助函数
引言 大学读的是一个很时髦的专业, 学了四年的游戏竞技. 可惜没学好. 但认真过, 比做什么都认真. 见证了 ...... 打的所有游戏人物中 分享一位最喜爱 的 “I've been alone ...
- linux下输入密码不回显
这几天在做一个登陆的程序,需要将输入的密码屏蔽掉,自己百度,找到了两种方法,先贴下第一种方法, #include<stdio.h> #include<unistd.h> int ...
- Go语言的web程序写法
一切来自于扩展... 核心也即处理输入输出... // helloworld project main.go package main import ( "fmt" "h ...
- 亲测能用的mysqli类,挺好用的
<?php header('content-type:text/html;charset=utf-8'); /* 掌握满足单例模式的必要条件 (1)私有的构造方法-为了防止在类外使用new关键字 ...
- Entity Framework中使用DbCompiledModel中遇到的坑和解决方案
前段时间,在公司做项目时,引入Entity Framework Code First的方法. 我们公司的软件为SaaS结构,有N个企业注册,其中SQL Server中有一张表为t_User_企业注册号 ...
- Qt发布可能遇到的问题
1.首先要搞清楚动态链接库还是静态链接 本文只涉及动态链接库,就是编译出来的exe文件加上Qt 的必要dll文件. 一般跟别人一样的操作,直接双击 XX.exe,提示缺少什么dll,就去Qt的安装目录 ...
- OpenStack 计算服务 Nova介绍和控制节点部署 (八)
一)nova在keystone上服务注册 1.1创建nova务实体 [root@controller ~]# source admin-openrc [root@controller ~]# open ...
- 一个纠结的Linux定时任务
昨天写了一个Linux定时任务,搞了半天才是搞好,现在分享下我犯得错误 首先在Linux根目录下创建一个目录 mkdir cat_crazy 进去创建一个shell脚本test.sh,内容是: #!/ ...