基本用法
最简单的情况是用它定义常量,即值不变的量
const int Constant = 1;
这会创建一个值为1的叫做Constant的常量
必须在声明时就赋值,因为常量是不可以再更改的
const也可以用来修饰指针,但是其在不同的位置会表示不同的含义
const int * Alpha
这声明了一个值可以变的指针,它指向一个不可变的整型常量
当需要使用一个函数返回常量型的字符串或数组时,会用到这种方式
int const * Alpha
这与上面的效果一样
int * const Bravo
这声明了一个值不可变的常量指针,它指向一个可变的整型
这种方式可以用于定义值可变,但地址不能变的元素
int const * const Charlie
将上面的两种结合,声明了一个值不可变的常量指针,它指向一个不可变的整型常量
可以总结出规律,const会优先对紧靠其左侧的元素生效,如果左侧没有东西,就会对紧靠其右侧的元素生效
函数返回值
由于字符串和数组是以指针形式被定义的,当需要用函数返回常量型的字符串或者数组时,使用const可以避免一些错误
假设用以下函数返回一个叫做Text的常量字符串
char *Function()
{
return "Text" ;
}
那么如果意外的执行了类似于下面的代码,程序就会崩溃
Function()[1] = 'a' ;
如果一开始Function是这样定义的
const char *Function()
{
return "Text" ;
}
那么编译器就会明白这个函数的返回值不能被修改
参数传递
当一个含有参数的函数或子线程被调用时,它可能会读入数据、写出数据或者既读入又写出
有些语言中可以明确定义数据的流向,它们含有类似于'in:' 'out:' 'inout:'的修饰符
C/C++中没有这些修饰符,需要用别的方法
void Subroutine(int Parameter)
{
printf ("&d", Parameter) ;
}
这个函数会使用C/C++的默认方式,通过复制Parameter(形参)来读入数据
这样它可以读取到Parameter的值,但不能够修改
当它执行完毕,这份数据的拷贝也就丢失了
当它执行完毕,这份数据的拷贝也就丢失了
void Subroutine(int Parameter)
{
Parameter = 20 ;
}
相同的原因,这个函数并不能够更改Paramter的值
但如果给变量名称前加上 &,那么函数就会接触到变量的本体,而非拷贝
void Subroutine(int &Parameter)
{
Parameter = 20 ;
}
Parameter会被更改为20,这种方法在C++中被叫做引用
然而在C中没有引用,需要通过指针来实现
void Subroutine(int *Parameter)
{
*Parameter = 20 ;
}
这种处理方式需要在被调函数和原函数中均使用指针处理变量,有些繁琐
那么这些和const有什么关系呢?
因为使用指针或者引用来传递数据,可能是为了对数据进行修改,也可能是为了提高程序执行效率
当函数所用到的数据很大时,复制会浪费很多的时间和空间
void Subroutine(huge_data &Parameter)
无法准确判断这个函数究竟是为了节省复制的时间,还是为了对数据进行修改
这时可以使用const消除歧义
void Subroutine(huge_data const &Parameter)
这表明这个函数不会对数据进行修改
理想情况下,应该不需要人为干预参数具体是怎么传递的这么细节的问题
但C设计的更加靠近底层,并且最初是运行于性能比现在低很多的计算机上
类
一个类中的方法(函数),它在处理自己的参数以及这个类中的其它成员变量时,都是直接传递而非复制传递
class Alpha
{
void Method() ;
int MemberVariable ;
}
Method不包含任何参数,但是它仍有修改MemberVariable的能力
void Class::Method()
{
MemberVariable++ ;
}
这个Method就会使MemberVariable的值加1
解决的方法是在方法的参数部分后面加上const
class Alpha
{
void Method() const ;
int MemberVariable ;
}
这将会禁止Method修改Alpha的任何成员变量
综合const的各种用法
const int*const Method(const int*const&) const ;
第一个表示Method返回的的指针指向的是一个常量
第二个表示Method返回的指针是一个常量指针
第三个表示Method不会修改所传入指针所指向的值
第四个表示传入Method的指针是一个常量指针
第五个表示Method不会修改类内的任何成员变量
麻烦
一个方法被const修饰后,它不能够修改任何成员变量
class Bravo
{
public:
void Output() const ;
private:
//Data
}
void Bravo::Output() const
{
//Output Data
}
Output方法用于输出数据
假如现在需要统计输出了几次,直接在Output内递增一个变量是不行的
这时可以用mutable,它会使被修饰的变量不受const的限制
class Bravo
{
public:
void Output() const ;
private:
//Data
mutable int counter ;
}
void Bravo::Output() const
{
//Output Data
counter++ ;
}