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修饰的成员函数(这一点要值得注意)

2.函数的返回类型用const修饰。如const A fun2( ); const A* fun3( );这样声明函数后,会起到相应的保护作用。eg. Test &Test ::Operator+(const Test &op1){ return *this},如果test类的+号运算符重载函数这样写,那么会出现这样的合法的代码,Test a; Test b; a+b=a;这种代码在语法上是没有什么异议的,但是在语义上终究是不通的。但是如果在函数前面加上const,那么这段代码在编译的时候就会出错的,这样也是对代码的一种保护。一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用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
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修饰的成员函数,

最新文章

  1. Bitset&lt;&gt;用于unordered container时的默认hash函数
  2. C# WebBrowser不能运行打开页面的activex
  3. LINUX测试环境部署nginx(五)
  4. 页面轮换,ViewFlipper 和 ViewPager 的区别
  5. NPM 使用介绍
  6. 手写DataSet,DataTable
  7. 你可以做一个更好的Coder为了自己的将来
  8. [Android Pro] ant 编译android工程
  9. CDH中,如果管理CM中没有的属性
  10. livereload的简单使用
  11. mac 下 sphinx + mysql + php 实现全文搜索(xampp)(3)sphinx 的配置项解析
  12. ural1424 Minibus
  13. Hibernate(四)
  14. 服务端技术进阶(八)GitHub入门篇
  15. git工具——对比文件的不同
  16. HttpWebRequest的Timeout和ReadWriteTimeout
  17. Eclipse 添加 lib (导入 .jar 包)
  18. eclipse Android项目 DDMS db文件 导出 Failed to pull selection null 问题
  19. JAVA高级篇(四、JVM垃圾回收和调优)
  20. Android工具

热门文章

  1. 64_l5
  2. uoj#35 后缀排序(后缀数组模版)
  3. 2017多校第8场 HDU 6138 Fleet of the Eternal Throne AC自动机或者KMP
  4. xtraTabControl学习
  5. jequry_rotate.js用来写旋转类的东西的插件(如:抽奖转盘)
  6. leetcode 之Candy(12)
  7. 查询 IDE 的版本 方便安装第三方的时候选择
  8. Guice2.0的变化——第一部分 新的特性(上)
  9. poj 3616(动态规划)
  10. MFC宏常识