posts - 14,comments - 2,trackbacks - 0
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 阅读(2316) 评论(2)  编辑 收藏 引用 所属分类: C++ Zealot!

FeedBack:
# re: const 的用法以及误区[未登录]
2010-06-07 22:05 | paul
const int *p = &b;

int *q = &b;

*q++;
这段代码能否通过编译,取决于b的声明状况吧?~  回复  更多评论
  
# re: const 的用法以及误区[未登录]
2010-06-08 22:03 | xlyz.os
是的,b是const当然就不能通过编译了@paul
  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理