目录
一、const关键字定义
如果一个变量被const所修饰,那么它的值就不可以被改变。当然,const也可以修饰函数参数,修饰函数返回值。
二、const关键字的用法
1.修饰局部变量(存放在栈区)
int const a = 1;
const int a = 1;
此时的两种写法效果相同,都是表示对局部变量a修饰,此时我们不可以在主函数中对该变量直接进行修改。
注:用const修饰变量时,一定要给变量初始化。如果不初始化,后面也就不能再初始化!
2.修饰全局变量(存放在全局静态存储区)
#include<stdio.h>
const int a = 1;
int main()
{
...
}
const修饰的全局变量放在常量区,其作用域是整个cpp文件,如果在后续函数中我们对其值进行修改,将会导致调用该变量的函数也出现bug。因此,我们一般会对全局变量用const修饰,防止其被非法篡改。
3.修饰常量静态字符串(存放在文字常量区)
const char* str='abcdefg';
字符串常量位于文字常量区,本身不允许被修改,所以我们一般用const来限定,这样就能让bug在编译的时候就能被发现,以防止其被非法修改导致程序崩溃。
注:const修饰的变量在C和C++的存储位置稍有差别,之后介绍。
4.const修饰指针
①常量指针(指向常量的指针)
const int* p1;
int const* p1;
常量指针指的是不能通过该指针修改变量的值,即该指针指向的值不能被改变。但是,该常量指针可以改变,它可以指向其他变量的地址。
②指针常量
int* const p1;
指针常量指的是该指针是一个常量,它所指向的地址不能被改变。但是,该指针指向的地址所存储的值是可以被改变的,我们可以通过指向该地址的其他指针来改变变量的值。
区分指针常量和常量指针:const在*左边->常量指针;const在*右边->指针常量。如果我们将*读作‘指针’,将const读作‘常量’,就可以快速区分了。
③指向常量的常指针
const int* const p1;
指向常变量的常指针即变量的值是不可以改变的,该指针所指向的地址也是不可以改变的。但依然可以通过其他指针来改变该变量的值。
5.const修饰数组
数组变量实际上就是const的指针,所以不能直接赋值。const修饰数组表明数组中的每个元素的数据类型都为const int,只能通过初始化来赋值且后续不能再被修改。
int arr[];//int* const a;指针常量//
const int arr[];//const int* const a;指向常量的常指针//
6.const修饰函数的参数
①当函数参数为值传递时:
值传递时,形参是实参的拷贝,函数修改的是拷贝中的值,不会影响实参的值,所以这时候加const限定无意义。
void fun(const int a);//无意义
void fun(int a);
②当函数参数为地址传递时(即形参为指针):
void fun(const char* p);//常量指针,无法通过指针修改外部实参
void fun(char* const p);//指针常量,防止修改指针指向的地址
void fun(const char* const p);//指向常量的常指针
③当函数参数为引用(C++):
引用传递时,引用就是对象的一个别名,因此不需要拷贝对象。该特性使得我们可以通过修改引用直接修改原始对象,所以我们有时为了避免原始对象被修改,我们会用const进行修饰。
MyString & operator=(const MyString &s);
7.const修饰函数返回值
①函数返回值采用”值传递“:
值传递会把返回值复制到外部临时的存储单元中,加const无意义。
int Get(void);
const int Get(void);//无意义
②函数返回值采用”指针传递“:
返回值加了const限定后,函数返回值(即指针)的内容不能被修改,该返回值只能赋给const限定的同类型指针。
const int* fun();
const int* p = fun();
int* p = fun();/*错误示例*/
注:①如果返回值为类对象时,我们一般采用引用传递直接在原始对象上修改其数值,从而跳过调用拷贝构造函数这一步骤,此时加上const,返回值就不容易被改变。
const A &fun(void);
②这里对函数返回值使用const的目的在于限制不可将函数调用表达式作为左值使用。
class A
{
public:
A& operator=(const A& s){
cout << "=" << endl;
if (this == &s)
return *this;
m_i = s.m_i;
return *this;
}
private:
int m_i;
}
void main()
{
A a(10);
A b(4);
A c(6);
a = b = c;
(a = b) = c;//该链式赋值是合法的
}
如果将赋值函数的返回值加const修饰,那么a=b=c仍然合法,但是(a=b)=c是非法的。
8.const修饰成员变量/成员函数
const修饰成员变量时,成员变量的值不能被修改,并且只能在构造函数中赋值。
const修饰成员函数时,我们称此函数为const成员函数,示例如下:
class A
{
public:
void Print()const{
...
}
/*//该成员函数实际上是这样
void Print(const A *const this){
...
}*/
private:
int m_i;
}
普通成员函数中,this指针为指针常量,它所指向的对象不可以被修改,但是其所指向的对象的成员变量可以被修改;const成员函数中,this指针变为指向常量的常指针,在该成员函数中我们不能对类对象的任何数据成员进行修改。
const对象只能调用const成员函数;非const对象既可以调用普通函数,也可以调用const成员函数。const成员函数能够访问对象的const成员,而其他函数不可以访问对象的const成员。