概念

  const就是为了直接表达“不变化的值”这一概念。也就是说该值只可读,不可直接写。
  由于不可以修改,所以const常量在声明的时候必须初始化

    const int a;    //error
extern const int ext_a;

作用

  • 可以定义const常量,具有不可变性

        const int a =  ;
    //a = 5; //error
  • 便于类型检查,使编译器对处理内容有更多了解
    如 a = 5 在编译的时候可以将对const常量进行修改的部分检查出来
  • 保护被修饰的内容
    我们一直在建议不要修改函数的参数值,便于调试、维护,以及减少不必要的错误,但函数的调用者与函数的编写者,所以无法人为的保证传入的参数无法被修改,此时就运用const,运用编译器对代码进行检查。主要还是和引用参数联合使用,如果只是修改参数对调用者没影响还好说,否则...(后续详谈)
    void fun1(const int a)
    {
    //a=5;
    } void fun2(const ClassA& a)
    {
    //a.xx=xx
    }
  • 提高代码的可读性、维护性
    运用const常量替换代码中出现的比较多的各种文字量,个人认为代码中出现数字0、1,阅读时还能理解,但是要是突然出来一个2、5、8,这是什么意思呢?可能自己写的代码过一阵子自己也不清楚了,此时我们就可以运用const常量或enum起一个合适的名字替代这些不易理解的数字。如果是字符串的话就只能运用const了,呃,或者是宏#define(个人不太喜欢宏,原因1.宏易出错,不易理解;2.编译器无法检查类型;3.C++不建议使用宏)
  • 函数重载
    两个重载函数必须在下列一个或两个方面有所区别:
    1、参数数量不同
    2、参数类型不同
      如下 funA以上两个方面都不满足,但是却可以重载,const函数对应const对象使用(后续详谈)
  • class ClassA
    {
    public:
    void funA()
    {
       //...
    } void funA() const
    {
    //...
    }
    }; 

const与指针

  The C++ Programming Language里面给出过一个助记的方法:  把一个声明从右向左读。

    char * const p1;          //p1 is a const pointer to char
const char *p2; //p2 is a pointer to const char
const char * const p3; //p3 is a const pointer to const char

  Effective C++同样给出了一种方式,如果关键字const在星号的左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;如果出现在两边,表示被指物和指针二者都是常量。其实指针只要分清指针本身与所指向的内容即可。个人觉得不用纠结与有些书上的叫法什么“指针常量”,“常量指针”,这都是在翻译的过程中带来的歧义。

  如p1是一个const pointer,所以在声明的时候必须初始化,否则编译不通过,而*p1则是char类型。
  p2是一个pointer但不是const,*P2才是const类型,所以p2可以不用初始化。

  那么p1声明指向的为char 是否可以指向const char 呢?p2声明指向的为const char 是否可以指向char类型呢?

    const char ca = 'a' ;
char b= 'b'; char *p;
//p=&ca; //error
p=&b;
char * const p1=&b;
//char * const p1=&ca; //error
const char *p2;
p2=&ca;
p2=&b; //ok
const char * const p3=&b; //ok

  因为对承诺不修改的内容要被修改,肯定是有问题的;但对可修改的内容不做修改没有任何问题。如上面ca不可修改,*p可以修改,所以p=&ca错误;而b可以修改,*p1不可以修改,p=&b对b不会造成不良影响,所以可以通过。

  那么是不是非const类型可以直接赋值与const类型呢?而const类型不能直接赋值与非const类型呢?

    ClassA ca;
const ClassA cst_b; ClassA cc=cst_b; //copy构造函数可以理解
ClassA c2;
c2=cst_b; //??
const ClassA cst_d=ca; int a=;
const int b=a;
int c=b; //??

  以上代码完全可以编译通过,那该怎么解释呢?个人理解为如果赋值后的对象不对原对象代码不良影响,都是可以通过的。如int c=b;c的修改不会修改b;c2=cst_b,调用ClassA的赋值操作ClassA& operator=(const ClassA&),也同样不会对原cst_b修改。

const与引用

  引用与指针有所不同,因为引用本身可以看作是一个常量指针,引用在声明是必须初始化,且不可以在引用值其他对象。所以引用只存在一种形式。const type& 而type& 与type& const 等价。const 引用主要运用在函数的参数传递方面。Effective C++ 第20条 Perfer pass-by-reference-to-const to pass-by-value.

    int a;
int & ref1=a;
const int & ref2 =a;
int & const ref3=a; //没必要

const与函数

  函数与const 的关系可以从三部分来看,返回值、参数、函数自身

  • const修饰返回值

    class ClassA
    {
    public:
    int a; ClassA():a()
    {
    }
    const int funA() //没意义,因为返回值本身就无法修改 与int funA()一样,而且也不存在funA()=4这种写法
    {
    return a;
    }
    int * const funB() //与funA一样,const的限定的是返回值的指针,也无法修改 。与int * funB() 一样
    {
    return &a;
    }
    const int * funC() //const修饰的是返回指针所指内容,所以该函数的接收这也必须为const int*类型
    {
    return &a;
    }
    const int &funD() //返回引用,该引用不可以修改
    {
    return a;
    }
    void test()
    {
    int re=funA();
    int *p= funB(); //int *p1=funC(); //error
    const int *p2=funC(); //int& c=funD(); //error
    const int& a2=funD(); }
    };

    funA、funB其实实际意义都不大,因为不论返回值是不是const类型,函数调用者都不可能修改返回值的实际值。而函数调用者该不该用const与函数本身没关系。
    cosnt自定义类型返回值,往往可以降低因函数调用者错误而造成的以外,而又不至于放弃安全性和高效性

    ClassA funCA()
    {
    ClassA a;
    return a;
    } int _tmain(int argc, _TCHAR* argv[])
    {
    ClassA ca;
    funCA()=ca;
      funCA()=ca;这句话具体有什么实际意义呢?没意义,但是就是可以编译通过,此时就可以将funCA返回值限定为const ClassA,这样的写法首先编译器都不通过。
  • const修饰函数参数
      Effective C++ 至于const参数,没什么特别新颖的观念,它们不过就像local const对象一样,你应该在必要使用它们的时候使用它们。除非你有需要修改参数或者loacl对象,否则请将他们声明为const。
        int funA(const int a);
    int funB(int * const p);
    int funC(const int *p);
    int funD(const int& ra);
  • const修饰成员函数自身
    将const实施于成员函数的目的,是为了确认该成员函数可以作用与const对象身上。这类函数有两个理由显得重要
    1.是class接口比较容易被理解。2.const对象使用
    class ClassA
    { public:
    int a; ClassA():a()
    {
    } void fun()
    {
    a=;
    cout<<"this is not a const function"<<endl;
    }
    void fun() const
    {
    // a=5; //error
    cout<<"this is a const function"<<endl;
    }
    };
    int _tmain(int argc, _TCHAR* argv[])
    { ClassA ca;
    ca.fun(); //this is not a const function const ClassA cb;
    cb.fun(); //this is a const function
    }

    const对象只能调用const函数,且const函数不能对成员函数做修改。若将void fun()函数删掉,则编译不通过错误提示:ClassA::fun”: 不能将“this”指针从“const ClassA”转换为“ClassA &;若将void fun() const 函数删掉,则ca.fun()调用const fun。

  今天快下班了,先写这些吧,明天补充总结!

C++ const学习的更多相关文章

  1. const学习(续)

    续接上一篇<C++ const学习> const与成员函数 之前说到了const修饰成员函数本身. const成员函数不能修改对象成员值 对于const或者费const对象都可以调用con ...

  2. ES6 let const学习

    1.let命令:用法类似于var,但是所声明的变量,只在let命令所在的代码块有效. 例:var a = [ ]; for(var i=0;i<10;i++){ a[ i ] = functio ...

  3. const 学习笔记

    #include<stdlib.h> #include<iostream> using namespace std; int main(){ // const 仅仅起到是否为常 ...

  4. ES6-个人学习大纲

    1,let   const学习补充 1.1,let的知识点: 01-作用域只限制在当前代码块内,代码块形式如下: { var str = '张三'; console.log(str); let str ...

  5. openssl 1.1.1 reference

    openssl 1.1.1 include/openssl aes.h: # define HEADER_AES_H aes.h: # define AES_ENCRYPT 1 aes.h: # de ...

  6. es6学习笔记1 --let以及const

    let语句的基本用法:  1.let声明的变量为块级作用域,只在最近的{}里面有效,如果在外部引用就会报错. { let a = 10; var b = "hello" } ale ...

  7. c++学习总结--复合类型,const。

    复习c++,有必要对一些东西做一下笔记,方便以后学习,如有问题,欢迎提出. 首先,最常用两种复合类型应该是引用和指针. 所谓复合类型,是在基本类型基础(如:int)上定义的类型. 引用是c++的一个复 ...

  8. c++ const 关键字 学习笔记

    const简单介绍: 1不再使用c中的#define,c++默认不给const定义的变量分配内存,所以它默认的是仅本文件可以看到该变量(即internal linkage), const int bu ...

  9. ES6-个人学习笔记一--let和const

    es6已经推出一段时间了,虽然在兼容和应用上还有不少的难题,但是其提供的未来前端代码编程的发展趋势和一些好用的功能还是很吸引人的,因此个人买了'阮一峰'先生的es6入门,希望对其有一个了解和学习,本系 ...

随机推荐

  1. Ubuntu 16.04中iptables的工具简介(iptables/iptables-restore/iptables-xml/iptables-apply/iptables-save)

    Ubuntu 16.04中安装的iptables版本为1.6.0,官方参考:http://www.linuxfromscratch.org/blfs/view/cvs/postlfs/iptables ...

  2. 踩坑录-mysql不允许远程连接(错误码:1130) Host'xxx.xxx.xxx.xxx' is not allowed to connect to this MySQL server“

    每次搭建mysql环境都会遇见同样的问题,在此分享一下踩坑笔录. 一.问题描述 安装成功后,本地直接链接远程mysql,默认为不允许远程访问,则客户端提示1130 - Host'xxx.xxx.xxx ...

  3. angular 的ui.router 定义不同的state 对应相同的url

    Angular UI Router: Different states with same URL? The landing page of my app has two states: home-p ...

  4. Ubuntu 16.04 LTS 搭建LAMP

    1. LAMP是一系列自由和开源软件的集合,包含了Linux.Web服务器(Apache).数据库服务器(MySQL)和PHP(脚本语言). Apache2 Web 服务器的安装 sudo apt i ...

  5. luajit利用ffi结合C语言实现面向对象的封装库

    luajit中.利用ffi能够嵌入C.眼下luajit的最新版是2.0.4,在这之前的版本号我还不清楚这个扩展库详细怎么样,只是在2.04中,真的非常爽.  既然是嵌入C代码.那么要说让lua支持 ...

  6. Cookies 初识 Dotnetspider EF 6.x、EF Core实现dynamic动态查询和EF Core注入多个上下文实例池你知道有什么问题? EntityFramework Core 运行dotnet ef命令迁移背后本质是什么?(EF Core迁移原理)

    Cookies   1.创建HttpCookies Cookie=new HttpCookies("CookieName");2.添加内容Cookie.Values.Add(&qu ...

  7. 华为云分布式数据库中间件DDM和开源MyCAT对比

    前言 华为云分布式数据库中间件(Distributed Database Middleware)是解决数据库容量.性能瓶颈和分布式扩展问题的中间件服务,提供分库分表.读写分离.弹性扩容等能力,应对海量 ...

  8. 配置Cocos Code IDE 可以正常运行的组合:jdk,sdk ,ndk, ant, cocos2d-x

    Cocos Code IDE:Cocos Code IDE 1.0.0-RC2 jdk:Cocos Code IDE 自动的jdk sdk:8以上 ndk:r9d(r10有bug),希望以后版本可以修 ...

  9. 网络流之最大流算法(EK算法和Dinc算法)

    最大流 网络流的定义: 在一个网络(有流量)中有两个特殊的点,一个是网络的源点(s),流量只出不进,一个是网络的汇点(t),流量只进不出. 最大流:就是求s-->t的最大流量 假设 u,v 两个 ...

  10. hdu 6035(树形dp)

    题意:给你棵树,树上每个节点都有颜色,每条路径上有m种颜色  问你所有路径上出现的颜色的和 思路:答案求的是每种颜色对路径的贡献  我们可以反过来每种颜色不经过的路径的条数 假设根节点的颜色为x  我 ...