const关键字是用来修饰一个变量使其成为常量(constant)的。常量只能在定义时进行初始化,而此后对这个变量的任何改变都将是非法的。const关键字在就是为了保证了它修饰的对象不被修改。
对于指针来说,const关键字同样可以保证它修饰的对象不被修改,但是与一般的对象有所不同,const可以指定指针本身为常量,也可以指定指针所指的对象为常量,亦或兼而有之。咱们看看下面这个例子:
char* p = "Hello" //#1
char* const p = "Hello" //const修饰指针p,#2
const char* p = "Hello" //const修饰指针所指向的内存, #3
const char* const p = "Hello" //const同时修饰指针以及所指内存 #4
想理解上面的4个例子,最关键,是要理解const的作用对象是什么。
#1,无论修改p还是*p都没有问题;
#2,可以修改*p,但不能修改已经被定义为常量的p,这相当于一个引用;
#3,const修饰指针p所指向的内存,所以指针可以修改,而这块内存不能修改;
#4,这是一种极端情况,一般来说,在编程中很少用到,它就相当于一个const的引用。
const还在函数的声明中体现出强大的功能。它可以指定一个函数的返回值,或者函数的参数;而对于类的成员函数,const还可以修饰其访问权限。
我们来看一个简单的例子:
class my
{
public:
const int& get() const; // #5
int& get(); // #6
private:
int m_n;
};
int my::get() const
{
return m_n;
}
int& my::get()
{
return m_n;
}
我们看到在my这个类中,有两个几乎相同的函数,为什么这样的函数也可以重载呢?它们居然有用了相同的参数列表,不过此时的参数列表是空的。
不用害怕,有后缀const存在,可保无虞!
那么我们就来看看,这个const到底干了些什么勾当。
对于普通的成员函数来说,C++编译器在调用它们的时候,都会隐式的提供一个this指针,所以,其实我们刚刚看到的那两个函数的参数列表不是空的,只不过编译器在欺骗我们,当然,我们可不会上它的当。那么现在,我们如此理解它们:
const int& get(my* this) const; // #7
int& get(my* this); // #8
这依然使我们产生了一些视觉上的不快,虽然,它们不再使空参数列表,但是参数列表好像还是相同,显然,如果真是这样,真两个函数肯定是无法重载的,那么问题一定就在哪个const后缀上。
那么现在,我就可以回答大家的疑问:在成员函数的后缀加上const之后,将会导致这个函数的参数列表轻微的改变,被影响的参数就是那个鬼鬼祟祟的this指针,this指针将会被const重新修饰。从而那两个函数,我们就可以写成这样:
const int& get(const my* this); // #9
int& get(my* this); // #10
OK
小功告成,现在,立即重载!
好,那么,如何去区分这两个函数不同的调用呢?
其实,只要理解了以上的思想,这已经不存在障碍了,只要我们能够让一个对象成为const类型,那么它就会自动去选择被后缀const修饰过的重载函数。
我们在前面提到过const可以修饰函数的返回值?这是怎么回事呢?对一个返回值进行修饰?有意义吗?
当然,当然。其实,这不是一个语法上的问题,而是一个逻辑上的问题。我们还是使用那个万人迷例子吧:
class my_int
{
public:
my_int(int n)
{
m_n = n;
}
my_int& operator+(my_int a);
private:
int m_n;
}
my_int& operator+(my_int a)
{
m_n += a.m_n;
return *this;
}
现在,我们返回的是一个my_int对象的引用,如果,我们不限定它是一个const类型的话,将会允许下面的这种怪物出现:
my_int a(3), b(5), c(19);
(a += b) = c;
显然,这是不应该被允许的一种表达式,对一个结果进行赋值,是一种非常愚蠢和丑陋的行为,所以,我们要这样修改我们的operator+函数:
const my_int& operator+(my_int a);
OK,一切大功告成,*****!!
转载自http://hi.baidu.com/idealsoft/blog/item/82bd8843a26515149213c647.html
————————————————————————————————————————————————————————————————
2011-11-03 16:45 22人阅读 评论(0) 收藏 举报
看 到const关键字,很多人想到的可能是const常量,其实关键字const并不能把变量变成常量!在一个符号前加上const限定符只是表示这个符号 不能被赋值。也就是它的值对于这个符号来说是只读的,但它并不能防止通过程序的内部(甚至是外部)的方法来修改这个值(C专家编程.p21)。也就是说 const变量是只读变量,既然是变量那么就可以取得其地址,然后修改其值。看来const也是防君子不防小人啊!:)
const 使用情况分类详析
1、const的普通用法
const int n = 10;
意思很明显,n是一个只读变量,程序不可以直接修改其值。这里还有一个问题需要注意,即如下使用:int a[n];在ANSI C中,这种写法是错误的,因为数组的大小应该是个常量,而n只是一个变量。
2、const用于指针
const int *p;;//P可变,*P不可变
int const *p;;//P可变,*P不可变
int * const p;;//P不可变,*P可变
在最后的一种情况下,指针是只读的(即p只读),而在另外两种情况下一样,指针所指向的对象是只读的(即*p只读)。const 是一个左结合的类型修饰符,它与其左侧的类型修饰符一起为一个类型修饰符,所以,int const 限定 *p,不限定p。int *const 限定p,不限定*p。这里有一个简便的区分方法:
沿着*号划一条线,如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。
3、const用于函数的地址传递参数
void foo(const int *p)
这种形式通常用于在数组形式的参数中模拟传值调用。也就是相当于函数调用者声称:"我给你一个指向它的指针,但你不能去修改它。"如果函数编写者遵循了这个约定,那么就相当于模拟了值传递。这也是const最有用之处了:用来限定函数的形参,这样该函数将不会修改实参指针所指的数据。这里注意了,是函数不应该去修改而不是不能修改,也就是说const不能阻止参数的修改
之所以把这作为一点来谈,就是因为有一些朋友可能会以为在函数参数中用了const就一定不可以改变
参数,这实际上是错误的理解,因为,它并不阻止参数的修改,下面举个简单的例子来阐述一下;
#include<ctype.h>
void ChangeStr(constchar*String)
int main(void){
//end
上面的程序把字符串中的每个字符都转换成大写字母了。因为*String把地址给了*Source,而*Source的值的改变编译器并不干涉,可能有的编译器会发出警告之类。上面的程序只是为了说明const并不会阻止参数的修改,如果象上面程序那样,个人感觉没什么意义,只会让人容易混乱而已。
const用法:定义常量,修饰指针、函数的输入参数和返回值,简单说const表示只读的意思,本质上来说它只是在全局数据段或者栈中定义的是一个只读的常量,不是真正位于字符串常量区。Const的目的是为了产生高质量的代码,提高代码的可读性,同时保护好不能被任意改变的内存,从而降低Bug产 生的概率。
const int a = 10;
const int b;//错误,常量必须初始化
int a = 10,b = 9;
const int *p1 = &a;//指针指向的内容只读,不能通过该指针去写
*p1 = 11;//错误
int * const p2 = &a;//指针本身只读,指针初始化到一个对象后,将不能被修改
p2 = &b;//错误
const int*p3 const= &a;//指针本身和指向的内容都是只读
const char *fp1(void) //修饰返回值,表示返回的指针指向内容只读
{
char *p = "dddd";
return p;
}
void fp1(const char *str)
{
*str = 4; //错误
const char *p = str;//p必须为const,才能接受str
}
int _tmain(int argc, _TCHAR* argv[])
{
const char *d = fp1();
printf("%s",d);
}
转载自 http://blog.youkuaiyun.com/yzy123456789/article/details/6932821