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修饰的成员函数,

c++中const使用详解的更多相关文章

  1. C++中const用法详解

    本文主要内容来自CSDN论坛: http://bbs.csdn.net/topics/310007610 我做了下面几点补充. 补充: 1. 用const声明全局变量时, 该变量仅在本文件内可见, 类 ...

  2. (转) C/C++中const关键字详解

    文章转自  http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777416.html 为什么使用const?采用符号常量写出的代码更容易维 ...

  3. C++中const关键字详解

    1.什么是const? const意味着是常量类型,被const修饰的变量或对象是不能被修改和更新的,当然在某些情况下,我们可以偷梁换柱的改变它. 2.为什么要引入const? 最初的目的是为了取代预 ...

  4. 【转载】C/C++中extern关键字详解

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  5. C++初学者 const使用详解

     关于C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,参考了康建东兄的const使用详解一文,对其中进行了一些补充,写下了本文. 1. const常量 如: cons ...

  6. C++中的STL中map用法详解(转)

    原文地址: https://www.cnblogs.com/fnlingnzb-learner/p/5833051.html C++中的STL中map用法详解   Map是STL的一个关联容器,它提供 ...

  7. const用法详解(转)

    http://www.cnblogs.com/StudyRush/archive/2010/10/06/1844690.html 面向对象是C++的重要特性. 但是c++在c的基础上新增加的几点优化也 ...

  8. ALSA声卡驱动中的DAPM详解之七:dapm事件机制(dapm event)

    前面的六篇文章,我们已经讨论了dapm关于动态电源管理的有关知识,包括widget的创建和初始化,widget之间的连接以及widget的上下电顺序等等.本章我们准备讨论dapm框架中的另一个机制:事 ...

  9. ALSA声卡驱动中的DAPM详解之六:精髓所在,牵一发而动全身

    设计dapm的主要目的之一,就是希望声卡上的各种部件的电源按需分配,需要的就上电,不需要的就下电,使得整个音频系统总是处于最小的耗电状态,最主要的就是,这一切对用户空间的应用程序是透明的,也就是说,用 ...

随机推荐

  1. mongodb 学习笔记--- 基础知识

    1.mongodb的安装 (1) mac使用brew 安装就好 brew install mongodb (2) mkdir /data/db 作为mongodb默认的数据目录 并 sudo chow ...

  2. 设计模式之笔记--组合模式(Composite)

    组合模式(Composite) 定义 组合模式(Composite),将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性.       组合模式有 ...

  3. SAE如何使用Git

    了解Git及远程git仓库 请先看博文<Git入门及上传项目到github中>,弄懂了之后我相信我下面说的就相当于废话了. SAE的git远程仓库就相当于github. 向SAE的远程仓库 ...

  4. jdk1.8在linux环境下的安装

    转自博客:http://www.cnblogs.com/ShawnYuki/p/6816179.html

  5. 12-4 NSString

    原文:http://rypress.com/tutorials/objective-c/data-types/nsstring NSString 在本教程的内容可能我们已经看到过很多次了,NSStri ...

  6. python中的map、reduce、filter、sorted函数

    map.reduce.filter.sorted函数,这些函数都支持函数作为参数. map函数 map() 函数语法:map(function, iterable, ...) function -- ...

  7. IntelliJ IDEA SpringBoot 使用第三方Tomcat以及部署

    花了半天时间终于成功,记录以备查阅. 一.第三方Tomcat部署 部署部分参考的是:把spring-boot项目部署到tomcat容器中 目标:把spring-boot项目按照平常的web项目一样发布 ...

  8. [设计模式-行为型]模板方法模式(Template Method)

    一句话 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中. 概括

  9. “无法识别的配置节system.webServer”解决办法

    在Winsows 2008 Server 上安装asp.net 1.1 的应用程序,在启用默认文档或者浏览目录时会向 web.config 文件添加 <system.webServer> ...

  10. SGU 261. Discrete Roots

    给定\(p, k, A\),满足\(k, p\)是质数,求 \[x^k \equiv A \mod p\] 不会... upd:3:29 两边取指标,是求 \[k\text{ind}_x\equiv ...