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