今天在做一个趋势笔试题的时候。才让我有了系统把constkeyword好好总结一下的冲动,由于这个关键词大大小小好多地方都出现过,出现频率很高,而每次仅仅是简短的把答案看了一下,没有真正将其整个使用方法弄透,立即要找工作了。为避免悲剧再次发生,不得不引起我的重视,这才有了这篇博文。

    首先。一看到constkeyword,我们的第一反应就是定义常量。的确。这没有错。const就是constant的缩写嘛,可是其实他的使用方法远不止这些。

接下来我们一一来解说。

    在C程序中,const的使用方法主要有定义常量、修饰函数參数和修饰函数返回值。

而在C++程序中。它除了上述功能外,还能够修饰函数的定义体,定义类中某个成员函数为恒态函数,即不改变类中的数据成员

。对于定义常量的使用方法,这里就不多说了,重点看一下修饰函数參数、修饰函数返回值以及修饰函数的定义体。

    0)修饰变量或指针
int ii=0; 
const int i=0;           //i是常量。i的值不会被改动 
  const int *p1i=&i;        //指针p1i所指内容是常量。能够不初始化 
int const* p11i = &i; //同上,const在*号左边,作用是一样的。
  int  * const p2i=ⅈ    //指针p2i是常量。所指内容可改动 
  const int * const p3i=&i; //指针p3i是常量。所指内容也是常量 
  p1i=ⅈ                 //合法 
  *p2i=100;               //合法
    1)修饰函数參数
    首先假设该參数用于输出,那么不管是採用指针传递还是引用传递,都不能加const修饰。所以const仅仅能用于修饰输入參数。这里又分三种情况:输入參数採用值传递还是指针传递还是引用传递。
    (1)假设採用值传递。因为函数将自己主动产生暂时变量用于复制该參数,该输入參数本来就无需保护,所以不须要加const 修饰。
     比如。对于函数void Func1(int x)。写成void Func1(const int x)一点意义也没有。

同理,对于void Func2(A a)也不须要写成void Func2(const A a),当中A为用户自己定义的对象类型。

    (2)假设採用指针传递,那么加const能够防止函数体内部对该參数进行改变。起到保护作用。
     比如。如果StringCopy函数定义为:void StringCopy(char *strDest, const char *strSrc)。那么,如果函数体试图改变strSrc的内容,编译器将报错。
    (3)假设採用引用传递。
     首先我们来说一下,为什么要引入引用传递这样的方法。原因是:对于非内部数据类型的參数而言,象void Func(A a) 这样声明的函数注定效率比較底。由于函数体内将产生A 类型的暂时对象用于复制參数a,而暂时对象的构造、复制、析构过程都将消耗时间。为了提高效率。能够将函数声明改为void Func(A& a)。这样一来,依据引用传递的定义,仅仅是借用了參数的别名,不须要产生暂时对象。
      可是,这样一来,当函数体中改变了參数a的值后,对应的传递的原始值也会对应改变。所以假设不希望改变原始參数。仅仅须要在前面加上const修饰。这样一来。函数终于定义为void Func(const A& a)。同理,是否应将void Func(int x) 改写为void Func(const int &x),以便提高效率?全然没有必要。由于内部数据类型的參数不存在构造、析构的过程,而复制也很快。“值传递”和“引用传递”的效率差点儿相当。
     总结一下const作为函数输入參数的使用方法:
     (1)对于非内部数据类型的输入參数,应该将“值传递”的方式改为“const 引用传递”,目的是提高效率。

比如将

void Func(A a) 改为void Func(const A &a)。

         (2)对于内部数据类型的输入參数。不要将“值传递”的方式改为“const 引用传递”。否则既达不到提高效率的目的,又减少了函数的可理解性。比如void Func(int x) 不应该改为void Func(const int &x)。
      2)修饰函数的返回值
      依据上面的思路,这里也分三种情况。即值传递、指针传递、引用传递。
      (1)假设函数返回值採用“值传递”方式,因为函数会把返回值拷贝到外部暂时的存储单元中,加const 修饰没有不论什么价值。
     比如,不要把函数int GetInt(void) 写成const int GetInt(void)。同理不要把函数A GetA(void) 写成const A GetA(void),当中A 为用户自己定义的数据类型。
    (2)假设函数返回值採用“指针传递”方式。那么函数返回值(即指针)的内容不能被改动,该返回值仅仅能被赋给加const 修饰的同类型指针。
     比如,定义函数为:const char *GetString(void),那么char *str = GetString()将会出现编译错误。应该写成const char *str = GetString()。
    (3)假设函数返回值是採用“引用传递”方式,它的意义在于能提供啊效率,而这样的方式使用场合并不多。这个时候,一定要搞清楚函数到底是想返回一个对象的“拷贝”还是仅返回“别名”就能够了,否则程序会出错。
     比如。对于类的重载赋值函数A & operate = (const A &other),假设不加cons修饰,则定义A a, b, c;(a = b) = c,程序合法。可是假设加上const修饰,即const A & operate = (const A &other)。则程序会报错。
       3)修饰函数的定义体。
       定义const函数。仅仅须要将constkeyword放在函数声明的尾部。不论什么不会改动类的数据成员的函数都应该声明为const 类型。

假设在编写

const 成员函数时,不慎改动了数据成员。或者调用了其他非const 成员函数。编译器将报错。这无疑会提高程序的健壮性。

    比如。下面程序中,类stack 的成员函数GetCount 仅用于计数,从逻辑上讲GetCount 应当为const 函数。编译器将指出GetCount 函数中的错误。
class Stack
{
public:
void Push(int elem);
int Pop(void);
int GetCount(void) const; // const 成员函数
private:
int m_num;
int m_data[100];
};
int Stack::GetCount(void) const
{
++ m_num; // 编译错误,企图改动数据成员m_num
Pop(); // 编译错误。企图调用非const 函数
return m_num;
}

    到这里,constkeyword的解说就结束了。下面是几点使用const的几点规则。
    1) const对象仅仅能訪问const成员函数,而非const对象能够訪问随意的成员函数,包含const成员函数。
    2) const对象的成员是不可改动的,然而const对象通过指针维护的对象却是能够改动的。
    3) const成员函数不能够改动对象的数据,无论对象是否具有const性质.它在编译时,以是否改动成员数据为根据,进行检查。
    4) 然而加上mutable修饰符的数据成员,对于不论什么情况下通过不论什么手段都可改动,自然此时的const成员函数是能够改动它的。

转载于:https://www.cnblogs.com/bhlsheji/p/5173445.html

C/C++中constkeyword相关推荐

  1. GNU Make 使用手册(于凤昌中译版)

    GNU Make 使用手册(中译版) 翻译:于凤昌 GNU make Version 3.79 April 2000 Richard M. Stallman and Roland McGrath 1 ...

  2. 面试:第十二章:所有总结

    Java基础 java基本类型哪些,所占字节 byte :1个字节 short :2个字节 char :2个字节 int :4个字节 long :8个字节 float :4个字节 double :8个 ...

  3. linux内核分析(转自某位大哥网上的笔记)

    启动 当PC启动时,Intel系列的CPU首先进入的是实模式,并开始执行位于地址0xFFFF0处的代码,也就是ROM-BIOS起始位置的代码.BIOS先进行一系列的系统自检,然后初始化位于地址0的中断 ...

  4. C语言:constkeyword、结构体

    前几节内容的解说,主要是内存地址及指针的分析.这一节解说一下easy混淆的keywordconstant及结构体的知识. 一.constkeyword 1. 字符常量的指针 char const *p ...

  5. 面向对象程序中的常量

    一.常数据成员 使用constkeyword进行说明的数据成员,称为常数据成员.其作用和使用方法与一般常变量(const变量)相似,但常数据成员的值是不能改变的. 注意:仅仅能通过构造函数的參数初始化 ...

  6. golang通过RSA算法生成token,go从配置文件中注入密钥文件,go从文件中读取密钥文件,go RSA算法下token生成与解析;go java token共用

    RSA算法 token生成与解析 本文演示两种方式,一种是把密钥文件放在配置文件中,一种是把密钥文件本身放入项目或者容器中. 下面两种的区别在于私钥公钥的初始化, init方法,需要哪种取哪种. 通过 ...

  7. 总结一下在使用某里云服务器的过程中出现过的一些问题

    此文总结在使用阿里云的过程中出现过的问题   想起来就记录一下 本人为言行负责! 海内选择腾讯华为,共勉! k8s不同命名空间的配置文件串掉了 k8s集群服务器购买上后,无法使用外网.连续购买了4台然 ...

  8. Kubernetes 中 设置pod不部署在同一台节点上

    在k8s中,节点的调度主要由亲和性和污点来进行控制的.   而在亲和性部分由分为了节点亲和性和节点反亲和性.   节点亲和性是指在pod部署时,尽量(软策略)或者必须满足(硬策略)部署在某些节点上. ...

  9. 在Dockerfile中设置G1垃圾回收器参数

    在Dockerfile中设置G1垃圾回收器参数 ENV JAVA_OPTS="\ -server \ -XX:SurvivorRatio=8 \ -XX:+DisableExplicitGC ...

最新文章

  1. 正则化技巧:标签平滑(Label Smoothing)以及在 PyTorch 中的实现
  2. 回京火车上编码是一种怎样的体验?
  3. mac搭建mongodb
  4. 理解MySQL--索引与优化(转载)
  5. 关于html-三角的制作
  6. 在python中使用什么工具管理模块_怎么使用Python pip(管理模块工具)
  7. iOS事件拦截(实现触摸任意位置隐藏指定view)
  8. Python3爬虫入门之Request库的使用
  9. linux安装了vnc服务器,Linux安装VNC服务及配置
  10. ThinkPHP商城分类无限分类遍历数据
  11. cmd命令行激活win7
  12. mac使用cjk和ctex宏包
  13. 嵌入式系统架构设计师的理解
  14. Java char类型介绍
  15. R语言使用rnorm函数生成正太分布数据、使用stem函数可视化茎叶图、茎叶图很直观的表现出数据的分布情况
  16. JPEG格式压缩算法
  17. jquery 报错提示Uncaught TypeError: $ is not a function
  18. [JZOJ4588]冷战
  19. 高级人工智能之语音识别
  20. 笔记本电脑右下角网络图标显示红叉

热门文章

  1. 2022-2028年全球与中国闪光棉市场研究及前瞻分析报告
  2. 2022-2028年中国汽车用胶管行业市场深度分析及投资前景趋势报告
  3. 在pycharm中无法引入同一目录下的python文件
  4. /etc/profile ,/etc/bashrc ,~/.bash_profile,~/ .bashrc 区别与联系
  5. ELMo解读(论文 + PyTorch源码)
  6. LeetCode简单题之七进制数
  7. VS Code搭建C/C++开发环境超详细教程
  8. 有了NPU,还要DSP吗?
  9. TVM在ARM GPU上优化移动深度学习
  10. GStreamer 1.0 series序列示例