一、定义
const是常量的意思,被其修饰的变量不可修改
C++程序员如果看到const关键字,如果只想到是常量,这可不是良好的条件反射。const更大的魅力在于可以修饰函数参数和返回值,甚至定义函数时也可以修饰。
二、被const修饰的变量特点
- 被修饰的普通变量无法更改其值
const int age = 10;
age = 20;//会报错
- 字符串常量必须用const类型修饰
const char *str = "hello world";
char *str = "hello world";//会报错
1、用const修饰函数的参数
如果函数的形式参数用于输出的情况下,无论是“指针传递”还是“引用传递”都不可以使用const修饰,否则该参数将失去输出功能。
- const只能修饰输入参数
//该函数无法运行,会报错;因为输出参数不可以用const修饰
int function(const int output, int input)
{
input = 10;
output = input + 10;
return output;
}
//当输入参数被const修饰时,不影响输出参数的使用
int function(int output, const int input)
{
output = input + 10;
return output;
}
int main()
{
int output=0,output1;
output1 = function(output, 10);
cout << output1 << endl;//输出20
getchar();
return 0;
}
- 输入参数采用“指针传递”,const修饰会有什么效果呢?
如果输入参数采用“指针传递”,那么const修饰可以防止意外的改动该指针指向的内存单元,起到保护内存变量的作用
void function(char *dst, const char* src)
{
//其中src是输入参数,dst是输出参数,如果函数体内部的语句试图更改src指向的单元,编译器将会报错
}
如果还想要保护指针本身,则可以声明指针本身为常量,防止该指针的值被更改
void function(char *dst, const char* const src)
{
//这样不仅指针src指向的内存单元不可被更改,而且本身的值也不可被更改,
}
- 输入参数采用“值传递”,const修饰会有什么效果呢?
如果输入参数采用“值传递”,由于函数将自动用实参的拷贝(即实参.copy)传递给形参,因此即使在函数内部修改了该参数,改变的也就是堆栈上实参的拷贝,而不是实参本身。因此实参的值并不会因为函数调用而被修改,所以一般不需要const修饰值传递参数
如果函数内部多次使用某个形参的初始值,即传入的参数值,那么在该形参前面加const修饰也就顺理成章
2、用const修饰函数的返回值
- 如果给“指针传递”的函数返回值加const修饰符,那么函数的返回值是一种“契约型”常量,不能被直接修改的同时,必须要同类型const指针的变量接收这个返回值
const char *GetString(void)
{
//函数体
}
char *str = GetString();//“初始化”: 无法从“const char *”转换为“char *”
const char *str = GetString();//正确!!
三、const修饰变量时位置不同,效果不同
const修饰int型变量
const int age = 20;
//age = 20;就会出错,const修饰的变量不可修改,即使更改的是源数值20
下方是:const修饰int型指针变量* p1,修饰的是* p1,所以* p1是常量,不可修改,即指针指向的内存单元不可更改;但p1不是常量,是地址变量,可以修改,这是因为const没有直接修饰p1
int value = 10;
int temp = 20;
//const修饰的是*p1,所以*p1是常量,不可修改;但p1不是常量,是地址变量,可以修改
const int *p1 = &value;
*p1 = 20;//报错
p1 = &temp;//不报错
//与上方相同,变量类型和const可以位置交换,没区别
int const *p2 = &value;
*p2 = 20;//报错
p2 = &temp;//不报错
const和int可以随意互换位置,不影响修饰的变量
下方是:const修饰int型指针变量p3,但const修饰的是p3本身(存放地址的指针),即p3这个int型指针变量不可能更改指向(也就是p3存放的地址值不可以更改)
int value = 10;
int temp = 20;
//const修饰的是p3,跟指针符号一点关系没有
int * const p3 = &value;
p3 = &temp;//报错,因为p3不可以更改指向
*p3 = 20;//不报错,因为没有直接修饰*p3,就可以更改指向的内容,结果value变成了20
下方表示的是,指针本身与指针指向的内容都被const修饰,所以都无法更改
//一个const修饰p4,所以p4是常量,另一个const修饰*p4,所以*p4也是常量,所以都无法修改
const int * const p4 = &value;
int const * const p5 = &value;
const int * 和 int const * 一样,const与数据类型交换不影响
一个万年不变的点就是const修饰是其右边的内容
四、总结
- 不希望某个值在代码其他地方改变时,可以给该变量用const变成常量,提高代码的‘健壮性’,也使得代码更加的安全
- 值传递不需要const修饰
- 引用传递用到const修饰的场合很多