谈谈C++中的const
2013-10-11 17:53
169 查看
const修饰变量
还是先从C谈起吧,在学习C语言的时候就知道const修饰的是常量,其值是不可改变的,真的是这样吗?
结果是2,但是a = 2则会报错,表明在C中const修饰的只是只读变量,本质上是可以被修改的!那么在C++里面呢?稍微修改一下上面的代码。
![](http://img.blog.csdn.net/20131011154357937)
咋一看,很奇怪的结果啊b与&a的值明明是一样的,怎么对其取值却不同呢?其实在C++中const才成为了真正的常量,对const修饰的变量不会为其分配内存空间,每次取用其时都会用符号表里面的值直接替换,但是为了兼容c语言在程序中有&a时还是会为其分配内存空间(当const常量为全局变量并需要在其他文件中引用或对其使用&取地址时会为其分配内存空间)。
由上可见在C++中const修饰的变量类似于宏定义,区别是:
const常量是由编译器处理的,提供类型检查和作用域检查;
宏定义由预处理器处理,单纯的文本替换
另外默认情况下C中的const是外联的,C++中时内联的,因此在C++中若要使用其他文件中定义的const常量则必须使用extern关键字。
该节的最后再介绍一下const退化。
从输出结果来看这里的const常量b,和c貌似和前面提到的C中的const常量一样,退化为了只读变量,这里解释一下,使用volaitle之后,该变量使用时每次都从内存中取值,故其退化为只读变量,对于变量b由于在编译期间不能直接确定其值故也退化为了只读变量!
const修饰指针
这里没什么好说的,左数右指,const在*左边,a指向的内容不可修改,右边指针本身不可被修改。
const引用
这里只是简单介绍一下,下面会有更详细的说明
先不管引用在编译器内部的实现(int &p ==const int *p)我们在使用的时候把他当成别名就可以了。有了上面的解释相信最后打印出2的结果也就不难理解了。
下面继续,看一下两段小程序
编译后发现第一段是错误的,这个是很好理解的,非const的引用怎么能用const变量初始化呢,那么下面的呢?
结果是编译不通过,但是如果改为const int &b = a;编译就可以通过了,比较奇怪?考虑其在编译器中的实现,以上代码翻译为
那么对b进行修改原意是修改a,但是从上面的翻译中修改b只会对temp临时变量的值进行修改,而不会对a产生任何作用,因此C++要求此种情况下引用类型必须为const,这样就不会产生模糊不清的状况了。
函数中的const
类中的const
const修饰引用时就变得很有必要了一是表明其在函数内为常量不可变,二也是比较常见的,我们都知道C++中的拷贝构造函数及赋值函数都是用了const引用,例如下例(Test表示类)
如果在赋值函数中没有const,上述的编译还能通过吗?(不能,原因const引用中已经介绍过)
终于到最后了,类中的const变量
在类中,有定义
那么该val怎么初始化呢?直接初始化时不行了,C++不允许这样做。C++中有初始化链表,可以在调用构造函数时对其进行初始化,初始化链表的调用顺序与在链表的顺序无关,只与起申明顺序有关,另其调用在构造函数前。
用法
构造函数后
当然按前面讲的,这里的const常量,已经退化为const只读变量了。
类中的const函数
const在函数末尾表示该函数内部不能对类中变量进行修改,因此上述代码是不可能编译通过的,在C++中变量定义前对需要修改的变量前面加上mutable即可修改!
还是先从C谈起吧,在学习C语言的时候就知道const修饰的是常量,其值是不可改变的,真的是这样吗?
int main() { const int a = 1; int *b = (int *)&a; *b = 2; printf("a = %d\n",a); return 0; }
结果是2,但是a = 2则会报错,表明在C中const修饰的只是只读变量,本质上是可以被修改的!那么在C++里面呢?稍微修改一下上面的代码。
int main() { const int a = 1; int *b = (int *)&a; *b = 2; printf("a = %d\n",a); printf("*b = %d\n",*b); printf("&a = %0x\n",&a); printf("&a = %0x",b); return 0; }
咋一看,很奇怪的结果啊b与&a的值明明是一样的,怎么对其取值却不同呢?其实在C++中const才成为了真正的常量,对const修饰的变量不会为其分配内存空间,每次取用其时都会用符号表里面的值直接替换,但是为了兼容c语言在程序中有&a时还是会为其分配内存空间(当const常量为全局变量并需要在其他文件中引用或对其使用&取地址时会为其分配内存空间)。
由上可见在C++中const修饰的变量类似于宏定义,区别是:
const常量是由编译器处理的,提供类型检查和作用域检查;
宏定义由预处理器处理,单纯的文本替换
另外默认情况下C中的const是外联的,C++中时内联的,因此在C++中若要使用其他文件中定义的const常量则必须使用extern关键字。
该节的最后再介绍一下const退化。
int main() { int temp = 1; const int b = temp; volatile const int c = temp; int *a1 = (int *)&b; int *a2 = (int *)&c; *a1 = 2; *a2 = 3; cout<<b<<endl; cout<<c<<endl; cin.get(); return 0; }
从输出结果来看这里的const常量b,和c貌似和前面提到的C中的const常量一样,退化为了只读变量,这里解释一下,使用volaitle之后,该变量使用时每次都从内存中取值,故其退化为只读变量,对于变量b由于在编译期间不能直接确定其值故也退化为了只读变量!
const修饰指针
这里没什么好说的,左数右指,const在*左边,a指向的内容不可修改,右边指针本身不可被修改。
const int *a; int const *a; //*a不可改变 int *const a; //a不可变,需在定义的时候初始化 const int *const a; //a及*a均不可变,需在定义的时候初始化
const引用
这里只是简单介绍一下,下面会有更详细的说明
int main() { const int &a = 1; //这里会为1分配内存空间,&指向这片内存空间 int *b = (int *)&a; // *b = 2; cout<<a<<endl; return 0; }
先不管引用在编译器内部的实现(int &p ==const int *p)我们在使用的时候把他当成别名就可以了。有了上面的解释相信最后打印出2的结果也就不难理解了。
下面继续,看一下两段小程序
const int a = 1; int &b = a; int a = 1; const int &b = a;
编译后发现第一段是错误的,这个是很好理解的,非const的引用怎么能用const变量初始化呢,那么下面的呢?
float a = 1.0; int &b = a;
结果是编译不通过,但是如果改为const int &b = a;编译就可以通过了,比较奇怪?考虑其在编译器中的实现,以上代码翻译为
float a = 1.0; int temp = a; int &b = temp;
那么对b进行修改原意是修改a,但是从上面的翻译中修改b只会对temp临时变量的值进行修改,而不会对a产生任何作用,因此C++要求此种情况下引用类型必须为const,这样就不会产生模糊不清的状况了。
函数中的const
void function(const int Var); //传递过来的参数在函数内不可以改变(无意义,因为Var本身就是形参) void function(const char* Var); //参数指针所指内容为常量不可变 void function(char* const Var); //参数指针本身为常量不可变(也无意义, 因为char* Var也是形参)
const int fun1() //无意义,参数返回本身就是赋值。 const int * fun2() //即指针内容不可变。 int* const fun3() //指针不可变,无意义
类中的const
void function(const Type &Var);
const修饰引用时就变得很有必要了一是表明其在函数内为常量不可变,二也是比较常见的,我们都知道C++中的拷贝构造函数及赋值函数都是用了const引用,例如下例(Test表示类)
const Test a; Test b; a = b;
如果在赋值函数中没有const,上述的编译还能通过吗?(不能,原因const引用中已经介绍过)
终于到最后了,类中的const变量
在类中,有定义
const int val;
那么该val怎么初始化呢?直接初始化时不行了,C++不允许这样做。C++中有初始化链表,可以在调用构造函数时对其进行初始化,初始化链表的调用顺序与在链表的顺序无关,只与起申明顺序有关,另其调用在构造函数前。
用法
构造函数后
Test():val(1) { ... }
当然按前面讲的,这里的const常量,已经退化为const只读变量了。
类中的const函数
class Test { private: int val; public : void setValue()const { val = 1; } };
const在函数末尾表示该函数内部不能对类中变量进行修改,因此上述代码是不可能编译通过的,在C++中变量定义前对需要修改的变量前面加上mutable即可修改!
相关文章推荐
- constexpr函数
- C/C++字符串查找函数
- c语言的本地化实现
- C++类成员默认初始化
- 使用c++编写动态链接库知道意见
- ZT C,C++表达式求值顺序 裘老的解释。 [问题点数:300分]
- [EffectiveC++]item35:考虑virtual函数以外的其他选择
- 并行编译加快 VS C++ 项目的编译速度
- vc++HOOK API黑客外挂编程必知必会
- c++ 拷贝构造函数调用时机
- vc++等待,延时处理,进程并行所必须
- C++ 基础教程
- vc++实现控制USB设备启用与否
- vc++实现Ring3全局HOOK
- vc++实现内核级进程保护
- VC++实现NAT穿透之NAT类型检测
- C++ 显式类型转换
- Java VS C++(3)可变参数...
- C++实现CString和string的互相转换(转)
- enum枚举类型赋值之switch语句与显示类型转换(Explicit Type Conversion)速度之比较