c++ const学习
2015-09-21 22:38
429 查看
1.什么是const?
const是限定符,用来修饰变量,使得它不可以被程序员修改值。
2.为什么需要const?
(1).作为常量的标志,#define的升级版本。
#define预定义处理,不能够确定类型。
#define会产生二义性,这一点在c陷阱与缺陷中有提到,比如#define typeA int *,定义
typeA a, b;会使b定义为int型。
(2).防止参数调用和函数返回值被意外改变,提供#define没有的功能。
(3).在类的设计中如果类的成员函数不改变类的成员数据,那么应当声明为const函数。
3.const的内存分配
const不像#define只是编译时替换,它会分配内存,也就是说,它的常量并非不可改变,只是
运行时在出现的地方替换为常量而已。因为const会分配内存,所以在类中不可以初始化const常量,
因为在类的对象还没有被创建时,系统找不到内存赋值,要在类中使用常量可以使用枚举或静态变量。
下面来看一组源码分析
从中可以看出,const变量在栈中分配内存,通过指针间接访问可以改变其内存,但是在输出的时候系
统是直接push 3将立即数压栈的,所以这是一个替换功能,保证了const的不可改变性。
4.常量指针或指针常量
int const *p =&a; //指针常量,不可以通过*p修改a的值
int * const p = &a; //常量指针,不可以修改p的地址
注意const在*的左右位置
5.全局常量的不可修改性
会报段错误,这里报错的原因在于:const int constant,这个全局常量内存分配在.rodata段,对于内
存分页机制来说,.rodata对应的页是只读的,当试图去修改该段内存时,会引发段错误。可以说,这
是真正能够保证不会被修改的常量。是在操作系统层面实现的。
6.c++ primier plus的作者建议尽量使用const。
const是限定符,用来修饰变量,使得它不可以被程序员修改值。
2.为什么需要const?
(1).作为常量的标志,#define的升级版本。
#define预定义处理,不能够确定类型。
#define会产生二义性,这一点在c陷阱与缺陷中有提到,比如#define typeA int *,定义
typeA a, b;会使b定义为int型。
(2).防止参数调用和函数返回值被意外改变,提供#define没有的功能。
(3).在类的设计中如果类的成员函数不改变类的成员数据,那么应当声明为const函数。
3.const的内存分配
const不像#define只是编译时替换,它会分配内存,也就是说,它的常量并非不可改变,只是
运行时在出现的地方替换为常量而已。因为const会分配内存,所以在类中不可以初始化const常量,
因为在类的对象还没有被创建时,系统找不到内存赋值,要在类中使用常量可以使用枚举或静态变量。
下面来看一组源码分析
<span style="font-size:14px;"> const int con_var1 = 3; int * b = (int *)&con_var1; *b = 5; std::cout <<con_var1 << " "<<*b <<std::endl; getchar();</span>vc++6.0的反汇编代码
<span style="font-size:14px;">004017A8 mov dword ptr [ebp-4],3 004017AF lea eax,[ebp-4] 004017B2 mov dword ptr [ebp-8],eax 004017B5 mov ecx,dword ptr [ebp-8] 004017B8 mov dword ptr [ecx],5 004017BE push offset @ILT+195(std::endl) (004010c8) 004017C3 mov edx,dword ptr [ebp-8] 004017C6 mov eax,dword ptr [edx] 004017C8 push eax //压栈参数 004017C9 push offset string " " (0046e01c) 004017CE push 3 //con_varl被替换成3 004017D0 mov ecx,offset std::cout (0047be90) 004017D5 call @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff) //调用输出函数 004017DA push eax 004017DB call @ILT+640(std::operator<<) (00401285) 004017E0 add esp,8 004017E3 mov ecx,eax 004017E5 call @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff) 004017EA mov ecx,eax 004017EC call @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0) 004017F1 mov ecx,dword ptr [__iob+4 (0047788c)] 004017F7 sub ecx,1 004017FA mov dword ptr [__iob+4 (0047788c)],ecx 00401800 cmp dword ptr [__iob+4 (0047788c)],0 00401807 jl main+9Bh (0040182b) 00401809 mov edx,dword ptr [__iob (00477888)] 0040180F movsx eax,byte ptr [edx] 00401812 and eax,0FFh 00401817 mov dword ptr [ebp-0Ch],eax 0040181A mov ecx,dword ptr [__iob (00477888)] 00401820 add ecx,1 00401823 mov dword ptr [__iob (00477888)],ecx 00401829 jmp main+0ABh (0040183b) 0040182B push offset __iob (00477888) 00401830 call _filbuf (00420b10) 00401835 add esp,4 00401838 mov dword ptr [ebp-0Ch],eax 0040183B xor eax,eax 0040183D pop edi 0040183E pop esi 0040183F pop ebx 00401840 add esp,4Ch 00401843 cmp ebp,esp 00401845 call __chkesp (004209b0) 0040184A mov esp,ebp 0040184C pop ebp 0040184D ret</span>
从中可以看出,const变量在栈中分配内存,通过指针间接访问可以改变其内存,但是在输出的时候系
统是直接push 3将立即数压栈的,所以这是一个替换功能,保证了const的不可改变性。
4.常量指针或指针常量
int const *p =&a; //指针常量,不可以通过*p修改a的值
int * const p = &a; //常量指针,不可以修改p的地址
注意const在*的左右位置
5.全局常量的不可修改性
<span style="font-size:14px;">#include<iostream> using namespace std; const int constant=1; int main() { unsigned int addr; int * pconst; addr=(unsigned int)&constant; pconst=(int *)addr; cout<<&constant<<" "<<&addr<<endl; *pconst=10;//segment fault cout<<constant<<endl; return 0; } </span>这里修改const后,会引发运行时错误。
会报段错误,这里报错的原因在于:const int constant,这个全局常量内存分配在.rodata段,对于内
存分页机制来说,.rodata对应的页是只读的,当试图去修改该段内存时,会引发段错误。可以说,这
是真正能够保证不会被修改的常量。是在操作系统层面实现的。
6.c++ primier plus的作者建议尽量使用const。
相关文章推荐
- 超简单的c语言程序
- 关于C++中的类型转换操作符
- 项目23.6 前导0的数字
- Effective c++笔记:03 尽可能使用const
- C语言程序初体验-第四课-第一题:计算长方形的周长和面积
- 【C语言】1000~2000之间的闰年
- C语言中宏定义和函数的取舍
- 项目23.5 我的加班费
- 项目23.4三角公式求值
- c++函数参数类型-引用
- 项目23.3两段函数求值
- C++ 版本的 行为树的简单实现
- 【C++】派生类构造函数
- message_flood
- c++打印*组成的任意等腰三角形
- C++: byte和int的相互转化
- c/c++面试1——字符串替换程序
- C++全局变量在多个源代码文件中的使用
- C++类的拷贝构造函数和赋值构造函数
- C++中POD类型