博客地址:http://blog.csdn.net/jiangxinnju

github:https://github.com/jiangxincode

首先说明一下const在C和C++中的主要用法,被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。它可以修饰变量、函数的参数、返回值,甚至函数的定义体。

const修饰变量

const修饰变量通常用于定义符号常量。我们过去一般使用宏定义的方式定义符号常量,比如:

#define PI3.1415926

其实我们也可以使用const方式定义符号常量,下面的语句与上面宏定义的方式达到的效果相似。

const double PI3.1415926

那两者有什么区别呢?在使用宏定义的方式时,首先在预处理过程中将源程序中的常量名全部替换成对应的字面常量,然后对替换过的源程序进行编译。相比较之下const方式不涉及预处理过程,它只在编译工程中起作用。因为宏定义方式定义的符号常量没有类型,所以不能进行严格的类型检查,而const则可以,并且有些调试工具可以对const常量进行调试,而不能对宏常量进行调试。但这也不是说宏常量就比const常量差,比如你能够利用const常量实现下面的宏定义功能么?

#ifndefJIANGXIN_H

#defineJIANGXIN_H

#endef

而且由于历史原因,实际上使用宏常量的情况远远大于const常量,特别是在纯C编程环境中。不过在C++编程环境中,我还是推荐你使用const,因为这更加安全。同时时刻记住一句话,const常量作用与编译期,宏常量作用于预编译期,当你遇到一些令人迷惑的问题时想想这句话,或许能够有所收获。

现在举几个例子:

const int m = 0; //其实我们通常把const符号常量叫做const常量,以便和宏常量区分

typedef char * pStr; //新的类型pStr,代表一个指向char的指针类型。

char string[4] = "abc";

const char *p1 = string;//p1是一个指针,指向一个const
char类型

p1++; //正确,p1本身不是常量,它指向一个常量

const pStr p2 = string; //p2是一个常量指针,这个指针指向一个char类型变量

p2++; //错误,p2是一个常量指针

char *const p3 = string; //p3同p2相同,是一个常量指针

char const* p4 = string; //p4同p1相同,是一个指向const
char的指针,只能用于C中,在C++中只能使用const
char *p4 = string;

const修饰函数形参

函数形参主要包括传值型参数,传指针型参数,传引用型参数。

对于传指针和传引用型参数,如果我们怕在该函数中错误的改变实参的值,一般都会加上const来修饰形参。

对于传值型参数,我们一般不会使用const修饰,因为完全没有必要,你是不是用const,都不能改变实参的值,因为传值型形参是在栈中分配的,函数调用之后一定会销毁。例如:void
Fun(int n)和void Fun(const int n)没有任何区别,而且还是代码更加晦涩,所以不推荐。但是有一种情况需要考虑,如果你需要传递一个比较复杂的类类型,但是你又不需要改变该类的对象,这时你可以将传值改为传指针或者引用,同时用const修饰。这样的话就避免了构造临时对象的开销。比如加入A是一个很复杂的类类型,这是使用void
Fun(const A &a)要比void Fun(A a)效率更高。

用const修饰函数的返回值

函数的返回值与形参类似,也包括返回值类型,返回指针类型,返回引用类型。

对于返回值类型为指针或者引用的情况,如果我们不希望其被修改,可以使用const对返回值进行限定。此时该返回值const修饰的同类型const指针(返回值为指针)或者同类型的const变量(返回值为引用,且该值为基本类型或者定义了拷贝构造函数、拷贝赋值运算符的类型)。如对于:

const char * Fun(void);

如下语句将出现编译错误:

char *str = Fun();//cannotconvert from 'const char *' to 'char *';

正确的用法是:

const char *str= Fun();

如果返回值类型为值类型,由于函数会把返回值复制到外部函数的存储单元中,加const修饰没有任何价值,所以不要把函数int
Fun(void) 写成const int Fun(void)。但是在某些情况下将值类型改为引用类型或者指针类型可以提高效率,可用不用const就看你要不要改变它们了。

const修饰成员函数

const关键字可以放在函数声明的尾部,表示该类成员不修改对象。注意const只能修饰类的成员函数,不能修饰普通函数,无论是C还是C++。

const 不再迷茫的更多相关文章

  1. let和const的区别

    es6语法中新增了 let和const 不再只是有var 1. let的用法 let是用来声明变量的,它和var的用法差不多,但是let所声明的变量只在它的代码块内有效,像for循环里用let会更好点 ...

  2. winform总结2> Action<> ,Action,func<>,委托相关的理解

    1,他们是什么: Action 封装一个方法,该方法不具有参数并且不返回值. Action<> 封装一个方法,该方法具有最多16个参数并且不返回值. func<> 封装一个具有 ...

  3. 游记——noip2016

    2016.11.18 (day 0) 呆在家. 悠闲地呆在家.. 明后天可能出现的错误: 1)没打freopen.打了ctime: 2)对拍程序忘记怎么写了...忘记随机化种子怎么写了: 3)不知道厕 ...

  4. 【转】一名大学生的PHP进阶之路

    我是一名河南某职业学院的学生,比较喜欢PHP开发 的 工作,自己也曾经自学过php,but如果没有老师教还真是难以坚持啊,在这里给大家说一下寒假在麦子的学习感受,首先说麦子每一堂课程都给了特别详细的 ...

  5. [Android Pro] Android Support 包里究竟有什么

    reference to : http://www.2cto.com/kf/201411/350928.html 随着 Android 5.0 Lollipop 的发布,Android 又为我们提供了 ...

  6. 报名|「OneAPM x DaoCloud」技术公开课:Docker性能监控!

    如今,越来越多的公司开始 Docker 了,「三分之二的公司在尝试了 Docker 后最终使用了它」,也就是说 Docker 的转化率达到了 67%,同时转化时长也控制在 60 天内. 既然 Dock ...

  7. [Effective Modern C++] Item 1. Understand template type deduction - 了解模板类型推断

    条款一 了解模板类型推断 基本情况 首先定义函数模板和函数调用的形式如下,在编译期间,编译器推断T和ParamType的类型,两者基本不相同,因为ParamType常常包含const.引用等修饰符 t ...

  8. EC读书笔记系列之14:条款26、27、28、29、30、31

    条款26 尽可能延后变量定义式的出现时间(Lazy evaluation) 记住: ★尽可能延后变量定义式的出现.这样做可增加程序的清晰度并改善程序效率 ----------------------- ...

  9. 如何让HTML的编写更具结构性

    首先声明,我不是搞技术的,很多词汇写的不够专业,但作为一枚菜鸟,我站在菜鸟的角度,来讲述我在学习技术的过程中所遇到的问题,和解决的方案. 入门HTML还算简单,无非是先写好固定的三对开闭标签结构:ht ...

随机推荐

  1. stuts-security.xml

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "- ...

  2. Duilib实现圆形头像控件

    .h文件 #ifndef __UIHEADICON_H__ #define __UIHEADICON_H__ /* 名称:圆形头像控件(派生CButtonUI类) */ class CHeadUI: ...

  3. 逐个后移,匹配符合要求的选项,ie7有bug

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  4. getElementsByClassName

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. UVA 442 二十 Matrix Chain Multiplication

    Matrix Chain Multiplication Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %l ...

  6. WebRTC的学习(二)

    英文原文的链接地址为:https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Overview WebRTC是由一些关联的API和协议一 ...

  7. linux下导入、导出mysql数据库命令

    一.导出数据库用mysqldump命令(注意mysql的安装路径,即此命令的路径): 1.导出数据和表结构: mysqldump -u用户名 -p密码 数据库名 > 数据库名.sql #/usr ...

  8. Hibernate 具体代码

    package com.shuyinghengxie.doudou; import static org.junit.Assert.*; import java.util.Date; import j ...

  9. Oracle 分页实现

    --分页实现------实行两行一页 --1 先查询按编号排序的所有用户信息 select t.* from T_USER t order by user_id ; --2 查询数据的前四行, ; - ...

  10. 经典JSP数据库连接(ORACLE、SQL Server、MySQL)

    1.连接ORACLE8/8I/9I数据库(thin模式) <%@ page language="java" import="java.util.*" pa ...