c/c++中const详解

c/c++中const详解

来自http://blog.csdn.net/lwbeyond/article/details/6187501

一. cons 的作用

(1) 可以定义 const 常量

  1. const int Max=100;
  2. int Array[Max];

(2) 可以保护被修饰的东西,防止意外的修改,增强程序的健壮性

如果在函数体内修改了i,编译器就会报错;

  1. void f (const int i)
  2. {
  3. i=10;//error!
  4. }

(3) 为函数重载提供了一个参考

  1. class A
  2. {
  3. ......
  4. void f(int i)       {......} //一个函数
  5. void f(int i) const {......} //上一个函数的重载
  6. ......
  7. };

(4) 可以节省空间,避免不必要的内存分配

  1. #define PI 3.14159         //常量宏
  2. const doulbe  Pi=3.14159;  //此时并未将Pi放入ROM中
  3. ......
  4. double i=Pi;               //此时为Pi分配内存,以后不再分配!
  5. double I=PI;               //编译期间进行宏替换,分配内存
  6. double j=Pi;               //没有内存分配
  7. double J=PI;               //再进行宏替换,又一次分配内存!

const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。

(5) 提高了效率
编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

二. 使用 const
(1) 修饰一般常量,常数组,常对象
修饰符const可以用在类型说明符前,也可以用在类型说明符后。 例如:

  1. //常量
  2. int const x=2;
  3. const int x=2;
  4. //常数组
  5. int const a[5]={1, 2, 3, 4, 5};
  6. const int a[5]={1, 2, 3, 4, 5};
  7. //常对象
  8. class A;
  9. const A a;
  10. A const a;

(2) 修饰指针

  1. const int *A;
  2. int const *A; //const修饰指向的对象,A可变,A指向的对象不可变
  3. int *const A; //const修饰指针A,     A不可变,A指向的对象可变
  4. const int *const A; //指针A和A指向的对象都不可变

<<effective C++>>上有个好记的方法:const在*号左边修饰的是指针所指的内容;const在*号右边修饰的是指针。
简单记就是:左内容,右指针。

也可以这样理解:先忽略类型名,然后看const离哪个近,就修饰谁。

如:const [int] *p; //先去掉int,这时const 修饰*p, p是指针,*p是指针指向的对象,不可变

(3) 修饰引用

  1. const double & v; //该引用所引用的对象不能被更新

(4) 修饰函数的返回值

const修饰符也可以修饰函数的返回值,返回值不可被改变,格式如下:

  1. const int Fun1();
  2. const MyClass Fun2();

(5) 修饰类的成员函数
const修饰符也可以修饰类的成员函数,格式如下:

  1. class ClassName
  2. {
  3. public:
  4. int Fun() const;
  5. .....
  6. };

这样,在调用函数Fun时就不能修改类里面的数据。

  1. class A
  2. {
  3. public:
  4. A(int i=0):test(i) {} //初始化列表
  5. private:
  6. const int i

(6) 在另一连接文件中引用const常量

  1. extern const int i;     //正确的引用
  2. extern const int j=10;  //错误!常量不可以被再次赋值

三. 几个要说明的问题
(1) 如何初始化类内部的常量?
方法1:初始化列表:

  1. class A
  2. {
  3. public:
  4. A(int num):i(num) //用num来初始化i
  5. {};
  6. private:
  7. const int i;
  8. };

方法2: 外部初始化

  1. class A
  2. {
  3. public:
  4. A() {}
  5. private:
  6. static const int i;   //注意必须是静态的
  7. };
  8. const int A::i=3;  //外部初始化


(2) 放在类内部的常量有什么限制?

  1. //error
  2. class A
  3. {
  4. public:
  5. A()
  6. {};
  7. private:
  8. const int c1 = 7;          //error
  9. static const int c2 = 7;   //error
  10. static int c3 = 7;         //error
  11. }
  12. //correct
  13. class A
  14. {
  15. public:
  16. A(int num):c1(num)
  17. {};
  18. private:
  19. const int c1;
  20. static const int c2;
  21. static int c3;
  22. }
  23. const int A::c2 = 7;  //不要加static
  24. int A::c3 = 7;        //不要加statci

这里是三种正确的初始化方法,要注意的是static在外部初始化时,不能再加上static标志。

3) const到底是不是一个重载的参考对象?
先看一个例子:

  1. class A
  2. {
  3. ......
  4. void f(int i)       {......} //一个函数
  5. void f(int i) const {......} //上一个函数的重载
  6. ......
  7. };

上面是重载是没有问题的了,那么下面的呢?

  1. class A
  2. {
  3. ......
  4. void f(int i)       {......} //一个函数
  5. void f(const int i) {......} //???
  6. ......
  7. };

这是个错误的,编译不通过。那么是不是说内部参数的const不予重载呢?

再看下面的例子:

  1. class A
  2. {
  3. ......
  4. void f(int&)       {......} //一个函数
  5. void f(const int&) {......} //???
  6. ......
  7. };

这个程序是正确的,看来上面的结论是错误的。为什么会这样呢?这要涉及到接口的透明度问题。
按值传递时,对用户而言,这是透明的,用户不知道函数对形参做了什么手脚,在这情况下进行重载是没有意义的,所以规定不能重载!

当指针或引用被引入时,用户就会对函数的操作有了一定的了解,不再是透明的了,这时重载是有意义的,所以规定可以重载。

时间: 2024-10-27 13:42:24

c/c++中const详解的相关文章

c++中const详解

C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,本人根据各方面查到的资料进行总结如下,期望对朋友们有所帮助. Const 是C++中常用的类型修饰符,常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的. 一.Const作用    如下表所示: No. 作用 说明 参考代码 1 可以定义const常量 const int Max = 100; 2 便于进行类型检查 const常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行

MySQL中EXPLAIN详解

MySQL中EXPLAIN详解 explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了: 如:explain select username,first_name form hx,itlearner where a.id=b.id EXPLAIN列的解释: id:本次 select 的标识符.在查询中每个 select都有一个顺序的数值. select_type :查询类

Linux中getopt详解

Linux中getopt详解 getopt函数用来解析命令行参数的,以'-'或'--'开头的参数为选项参数,选项参数除去'-'或'--'的剩下的是选项字符.如果getopt函数被重复调用,则它将会依次返回每个选项元素中的选项字符. 使用getopt需使用以下头文件: #include<unistd.h> #include<getopt.h> 有几个全局变量与getopt函数解析参数有关: optind: int型, 指示下一个要解析的参数位置,初始时为1. optarg: char

Android中Context详解 ---- 你所不知道的Context

转载至 :http://blog.csdn.net/qinjuning 前言:本文是我读<Android内核剖析>第7章 后形成的读书笔记 ,在此向欲了解Android框架的书籍推荐此书. 大家好,  今天给大家介绍下我们在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中 时刻的在与它打交道,例如:Service.BroadcastReceiver.Activity等都会利用到Context的相关方法 : 说它陌生,完全是 因为我们真正的不懂Context

Android中Context详解 ---- 你所不知道的Context (转载)

Android中Context详解 ---- 你所不知道的Context (转载) http://blog.csdn.net/qinjuning 大家好,  今天给大家介绍下我们在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中 时刻的在与它打交道,例如:Service.BroadcastReceiver.Activity等都会利用到Context的相关方法 : 说它陌生,完全是 因为我们真正的不懂Context的原理.类结构关系.一个简单的问题是,一个应用

Python中dict详解

yangyzh Python中dict详解 python3.0以上,print函数应为print(),不存在dict.iteritems()这个函数. 在python中写中文注释会报错,这时只要在头部加上# coding=gbk即可 #字典的添加.删除.修改操作dict = {"a" : "apple", "b" : "banana", "g" : "grape", "o&qu

winxp计算机管理中服务详解

winxp计算机管理中服务详解01 http://blog.sina.com.cn/s/blog_60f923b50100efy9.html http://blog.sina.com.cn/s/blog_b08c76100102vijm.html winxp计算机管理中服务详解02 http://blog.sina.com.cn/s/blog_60f923b50100efz3.html http://blog.sina.com.cn/s/blog_b08c76100102vijn.html

【转】 java中HashMap详解

原文网址:http://blog.csdn.net/caihaijiang/article/details/6280251 java中HashMap详解 HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实现类.虽然 HashMap 和 HashSet 实现的接口规范不同,但它们底层的 Hash 存储机制完全一样,甚至 HashSet 本身就采用 H

转:iOS中socket详解

一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象: 传输层.会话层.表示层和应用层则被称作主机层,是用户所面向和关心的内容. http协议   对应于应用层 tcp协议    对应于传输层 ip协议     对应于网络层 三者本质上没有可比性.  何况HTTP协议是基于TCP连接的. TCP/IP是传输层协议,主要解决数据如何在网络