const 常见用法
const是C++语言的一种关键字,起受保护,防止以外的变动的作用!可以修饰变量,参数,返回值,甚至函数体。const可以提高程序的健壮性,你只管用到你想用的任何地方。
1. const修饰参数。const只能修饰输入参数。
1)如果输入参数是指针型的,用const修饰可以防止指针所指向的内容被意外修改。
2)如果参数采用值传递的方式,无需const,因为函数自动产生临时变量复制该参数。
3)非内部数据类型的参数,需要临时对象复制参数,而临时对象的构造,析构,复制较为费时,因此建议采用前加const的引用方式传递非内部数据类型。而内部数据类型无需引用传递。
2. const修饰函数返回值。
1)函数返回const指针,表示该指针不能被改动,只能把该指针赋给const修饰的同类型指针变量。
2)函数返回值为值传递,函数会把返回值赋给外部临时变量,用const无意义!不管是内部还是非内部数据类型。
3)函数采用引用方式返回的场合不多,只出现在类的赋值函数中,目的是为了实现链式表达。
3. const+成员函数。任何不修改数据成员的函数都应该声明为const类型,如果const成员函数修改了数据成员或者调用了其他函数修改数据成员,编译器都将报错!
【误区1】
const int* a = &b; /* [1]*/
int const *a = &b; /* [2]*/
int* const a = &b; /* [3]*/
const int* const a = &b; /* [4]*/
看看上面的4行代码,或许可以这么理解:
如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。因此,[1]和[2]的情况相同,都是指针所指向的内容为常量(const放在变量声明符的位置无关),这种情况下不允许对内容进行更改操作,如不能*a = 3 ;[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;[4]为指针本身和指向的内容均为常量。
但是我想上面的解释不一定正确. 关于const int* a = &b, 并不是说a所指向的是常量,而应该理解成: a所指向的内容不能通过*a来改变,对于a所指向的内容是不是常量并没有限制。如下面的代码,是可以通过编译的。
const int *p = &b;
int *q = &b;
*q++;
【误区2】C++中的const 是具有内部链接的( 不同于C)
下面是摘自C++中关于链接的一段话:
— When a name has external linkage, the entity it denotes can be referred to by names from scopes
other translation units or from other scopes of the same translation unit.
— When a name has internal linkage, the entity it denotes can be referred to by names from other scope
the same translation unit.
— When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.
A name having namespace scope (3.3.5) has internal linkage if it is the name of
— an object, reference, function or function template that is explicitly declared static or,
— an object or reference that is explicitly declared const and neither explicitly declared extern nor
previously declared to have external linkage; or
— a data member of an anonymous union.
从上面可以看出const对象是具有内部链接的。
内部链接的意思就是:
/*----A.h------*/
int a;
const int b;
/*----test1.cc-------*/
#include “A.h”
/*----test2.cc-------*/
#include “A.h”
当test1.cc 和test2.cc 链接的时候,a会出现变量重定义的错误,而b是不会的。因为b是具有内部链接的变量,相当于在test1.cc和test2.cc中各有一份b的符号。
const变量放在头文件中是不会引起链接时候的重复定义的,但是也不推荐将const变量放在头文件中。
const变量不是在编译的时候进行常量折叠,相当于宏的替换,const变量是不占内存的。
但是 在某一些情况下,编译器会为const分配内存,比如:
const int a = 10;
const int *p = &a;
当你想获取const变量的地址时(当然你也可以将a的地址打印出来看看),编译器就会强制为const变量分配内存了。所以当你在含有const变量的头文件被多个编译单元包含时,const变量也有可能在编译单元中占据内存。所以一般是不推荐将const 或者static变量放在头文件中。当然这样做也无可厚非。
下面这种情况const也是会分配内存的:
const int a[5] = {1, 2, 3, 4, 5};
所以下面的语句也就自然而然是不能通过编译的了:
int arr[a[2]];
虽然a[2]的类型也是const int,但是它与下面的这种情况是有区别的:
const int k = 3;
int arr[k];
因为k是const 类型,在编译的时候进行了常量折叠。而上面的a[2]虽然也是const int型,但是它存在于内存中。数组声明时数组的维数是不允许用内存中的数据来定义的。所以编译器会在此报出illegal的错误。
当然可能不同的编译器会有不同的编译结果。比如在gcc下你编译上述的代码会诡异的通过,但是这是不符合C++标准的。当然如果你加上参数-pedantic的话,你就会发现编译器乖乖的听你的话了。
const变量在大部分情况下是编译时的常量,如果需要运行时的常量,应该怎么做呢?像下面的代码这样:
const int const_runtime = get_v() // get_v在其他地方定义
又或者对运行时的变量加锁,让其变为只读的? 不管怎样,要想获得运行时的常量,方法还是很多的。欢迎交流。
上述只是个人理解,如有错误的地方,还望指教.
posted on 2010-06-06 10:00
Jiggy.Stone 阅读(2333)
评论(2) 编辑 收藏 引用 所属分类:
C++ Zealot!