C++ const实现原理
2016-03-21 17:36
246 查看
const 用于修饰常量时,分两种情况
1. 被修饰的常量是基本类型
此时,程序在编译时,就将变量用常量来替换了。
ps:
基本数据类型如下:
2. const 变量修饰的是非基本类型。
此时,程序编译时,不知道该用什么值替换再编译;所以,将会用一块内存地址替换,然后再编译。
运行结果:
const用于修饰函数也包含两种情况
1. const在函数名前。
此种情况下表示,该函数返回值的类型使一个const类型。
2. const在成员函数名之后
此种情况下表示,该函数中将不会对改类的成员变量做任何改变。
1. 被修饰的常量是基本类型
此时,程序在编译时,就将变量用常量来替换了。
实现机制:这些在编译期间完成,对于内置类型,如int,编译器可能使用常数直接替换掉对此变量的引用。而对于结构体不一定。
看下面的例子:
const int j=100; int *p=const_cast<int*>(&j); *p=200; cout<<j<<endl; 输出为什么是100呢? cout<<*p<<endl; //输出是改过的200 编译器在优化代码时把cout<<j直接优化成cout<<100了,所以虽然p和&j的值一样,但cout<<j不再通过访问j的地址输出。(反汇编时也有看到直接把数字压栈push 100 ) 这是因为,const型在压栈时,是使用的直接的数,就有点像C的#define a 100 |
基本数据类型如下:
Name | Description | Size* | Range* |
---|---|---|---|
char | Character or small integer. | 1byte | signed: -128 to 127 unsigned: 0 to 255 |
short int( short) | Short Integer. | 2bytes | signed: -32768 to 32767 unsigned: 0 to 65535 |
int | Integer. | 4bytes | signed: -2147483648 to 2147483647 unsigned: 0 to 4294967295 |
long int( long) | Long integer. | 4bytes | signed: -2147483648 to 2147483647 unsigned: 0 to 4294967295 |
bool | Boolean value. It can take one of two values: true or false. | 1byte | trueor false |
float | Floating point number. | 4bytes | +/- 3.4e +/- 38 (~7 digits) |
double | Double precision floating point number. | 8bytes | +/- 1.7e +/- 308 (~15 digits) |
long double | Long double precision floating point number. | 8bytes | +/- 1.7e +/- 308 (~15 digits) |
wchar_t | Wide character. | 2 or 4 bytes | 1 wide character |
此时,程序编译时,不知道该用什么值替换再编译;所以,将会用一块内存地址替换,然后再编译。
#include <iostream> using namespace std; struct A { int i; char ch; A() { i = 100; ch = 'S'; } }; int main() { const A a; const int i = 200; int *p1 = (int*)&a.i; int *p2 = (int*)&i; *p1 = 1; *p2 = 2; //a.i = 200; //报错,左值不能为const cout << a.i << " " << a.ch << endl; cout << i << endl; return 0; }
运行结果:
1 S 200 |
1. const在函数名前。
此种情况下表示,该函数返回值的类型使一个const类型。
<span style="font-family: FangSong_GB2312;"><u>例如函数 </u></span><span style="font-family: FangSong_GB2312;"><span style="white-space: pre;"> </span>const char * GetString(void); </span><span style="font-family: FangSong_GB2312;"><span style="white-space: pre;"> </span>如下语句将出现编译错误:</span><span style="font-family: FangSong_GB2312;"> <span style="white-space: pre;"> </span>char*str = GetString(); </span><span style="font-family: FangSong_GB2312;"><span style="white-space: pre;"> </span>正确的用法是</span><span style="font-family: FangSong_GB2312;"> <span style="white-space: pre;"> </span>const char *str =GetString();</span>
2. const在成员函数名之后
此种情况下表示,该函数中将不会对改类的成员变量做任何改变。
<span style="font-family: FangSong_GB2312; color: rgb(255, 0, 0);"><span style="white-space: pre;"> </span>任何不会修改数据成员的函数都应该声明为const</span><span style="font-family: FangSong_GB2312; color: rgb(255, 0, 0);">类型。</span><span style="font-family: FangSong_GB2312;">如果在编写</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">成员函数时,不慎修改了数据成员,或者调用了其它非</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">成员函数,编译器将指出错误,这无疑会提高程序的健壮性。以下程序中,类</span><span style="font-family: FangSong_GB2312;">stack</span><span style="font-family: FangSong_GB2312;">的成员函数</span><span style="font-family: FangSong_GB2312;">GetCount</span><span style="font-family: FangSong_GB2312;">仅用于计数,从逻辑上讲</span><span style="font-family: FangSong_GB2312;">GetCount</span><span style="font-family: FangSong_GB2312;">应当为</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">函数。编译器将指出</span><span style="font-family: FangSong_GB2312;">GetCount</span><span style="font-family: FangSong_GB2312;">函数中的错误。</span><span style="font-family: FangSong_GB2312;"> classStack { <span style="white-space: pre;"> </span>public: <span style="white-space: pre;"> </span>void Push(int elem); <span style="white-space: pre;"> </span>int Pop(void); <span style="white-space: pre;"> </span>int GetCount(void) const; // const </span><span style="font-family: FangSong_GB2312;">成员函数</span><span style="font-family: FangSong_GB2312;"> <span style="white-space: pre;"> </span>private: <span style="white-space: pre;"> </span>intm_num; <span style="white-space: pre;"> </span>int m_data[100]; };</span>
<span style="font-family: FangSong_GB2312;"> int Stack::GetCount(void)const { <span style="white-space: pre;"> </span>++ m_num; // </span><span style="font-family: FangSong_GB2312;">编译错误,企图修改数据成员</span><span style="font-family: FangSong_GB2312;">m_num <span style="white-space: pre;"> </span>Pop();// </span><span style="font-family: FangSong_GB2312;">编译错误,企图调用非</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">函数</span><span style="font-family: FangSong_GB2312;"> <span style="white-space: pre;"> </span>return m_num; }</span>
<span style="font-family: FangSong_GB2312;"> const </span><span style="font-family: FangSong_GB2312;">成员函数的声明看起来怪怪的:</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">关键字只能放在函数声明的尾部,大概是因为其它地方都已经被占用了。</span><span style="font-family: FangSong_GB2312;"> </span><span style="font-family: FangSong_GB2312;">关于</span><span style="font-family: FangSong_GB2312;">Const</span><span style="font-family: FangSong_GB2312;">函数的几点规则:</span><span style="font-family: FangSong_GB2312;"> a.const</span><span style="font-family: FangSong_GB2312;">对象只能访问</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">成员函数</span><span style="font-family: FangSong_GB2312;">,</span><span style="font-family: FangSong_GB2312;">而非</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">对象可以访问任意的成员函数</span><span style="font-family: FangSong_GB2312;">,</span><span style="font-family: FangSong_GB2312;">包括</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">成员函数</span><span style="font-family: FangSong_GB2312;">. b.const</span><span style="font-family: FangSong_GB2312;">对象的成员是不可修改的</span><span style="font-family: FangSong_GB2312;">,</span><span style="font-family: FangSong_GB2312;">然而</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">对象通过指针维护的对象却是可以修改的</span><span style="font-family: FangSong_GB2312;">. c.const</span><span style="font-family: FangSong_GB2312;">成员函数不可以修改对象的数据</span><span style="font-family: FangSong_GB2312;">,</span><span style="font-family: FangSong_GB2312;">不管对象是否具有</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">性质</span><span style="font-family: FangSong_GB2312;">.</span><span style="font-family: FangSong_GB2312;">它在编译时</span><span style="font-family: FangSong_GB2312;">,</span><span style="font-family: FangSong_GB2312;">以是否修改成员数据为依据</span><span style="font-family: FangSong_GB2312;">,</span><span style="font-family: FangSong_GB2312;">进行检查</span><span style="font-family: FangSong_GB2312;">. e.</span><span style="font-family: FangSong_GB2312;">然而加上</span><span style="font-family: FangSong_GB2312;">mutable</span><span style="font-family: FangSong_GB2312;">修饰符的数据成员</span><span style="font-family: FangSong_GB2312;">,</span><span style="font-family: FangSong_GB2312;">对于任何情况下通过任何手段都可修改</span><span style="font-family: FangSong_GB2312;">,</span><span style="font-family: FangSong_GB2312;">自然此时的</span><span style="font-family: FangSong_GB2312;">const</span><span style="font-family: FangSong_GB2312;">成员函数是可以修改它的</span>
相关文章推荐
- OC语言入门
- 应用:C语言通讯录---搜索联系人
- 应用:C语言通讯录---修改联系人
- 应用:C语言通讯录---删除联系人
- 应用:C语言通讯录---添加联系人
- 应用:C语言通讯录---查看联系人
- 应用:C语言通讯录---初始化
- 应用:C语言通讯录---退出系统
- 应用:C语言通讯录---界面和框架搭建
- 应用:C语言通讯录---功能实现步骤分析
- 应用:C语言通讯录---知识点分析
- 应用:C语言通讯录---功能展示
- VC++从入门到精通视频教程网址
- C++模板
- C语言模块化编程的思想
- jenkins编译C或C++程序
- 【poj 1321】 棋盘问题 题解&题意&代码(C++)
- C++ typeid关键字详解
- MFC程序最小化到托盘
- C语言之基本算法32—鞍点