您的位置:首页 > 编程语言 > C语言/C++

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常量,

因为在类的对象还没有被创建时,系统找不到内存赋值,要在类中使用常量可以使用枚举或静态变量。

下面来看一组源码分析

<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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: