const的用法
const是C++语言引入的一个关键字,是“不变的”、“常量”的意思。用const定义的变量,实际上是定义了一个“只读变量”,const组合变量的用法比较容易理解,但是如果配合指针、引用和函数等,就不容易理解,接下来由四个方面介绍const的用法
1. const的位置
const的位置比较灵活,一般来说,除了修饰一个类的成员函数外,const不会出现在一条语句的最后
const使用实例:
#include <iostream>
using namespace std;
int main()
{
int i = 5;
const int v1 = 1;
int const v2 = 3;
const int* p1;
int const *p2;
int *const p3 = &i;
const int * const p4 = &v1;
int const * const p5 = &v2;
const int &r1 = v1;
int const &r2 = v2;
cout << *p4 << endl;
return 0;
}
程序最终运行结果为1
以上程序演示的是const的位置与其语义之间的关系。const和数据类型相结合,形成所谓的"常类型",然后常类型再定义变量,就产生了常变量
需要注意的是:
-
const用来修饰类型的时候,其位置是可以变化的,既可以放在类型前,又可以放在类型后
-
使用常类型修饰变量时,只能放在变量名后
-
const和被修饰类型之间不能有其它标识符
如下几种情况会编译失败
const * int p3; //情况3
int * const p3; //情况2
const & int r3; //情况3
int & const r4 = i; //情况2
在理解有const存在的声明语句时,需要明白“不可变”的到底是什么
- 对一个具体变量来说,如果const直接出现在变量的前面时,则该变量的值一旦被初始化,就不能再被改变,即const int v1;和int const v1;都是合法的,且二者等价
- int const *p;和int * const p;则是不同的声明语句
- 前一个const修饰的是int类型变量,而后者修饰的则是int *
- 前者表示指针p指向的是一个只读的整形变量,即指针所指向的单元的内容不允许被修改,而指针本身可以指向其它的常变量;但是后者表示指针p一旦指向一个整型变量之后,就不能再指向其它的变量,且指针一旦被定义为指针常量,必须对其进行初始化,否则编译将报错
- 引用的底层实现本来就是只读指针,因此在引用前使用const是没有意义的
- 常引用是将被引用的对象当做一个常量,也就是不允许通过引用来修改被引用对象的值
2.const对象和对象的const成员
用const来定义一个基本类型的变量,是值不允许显式的修改该变量的值
如果用const来定义某个类的对象,则情况更加复杂,因为对象不仅包含成员变量,还有成员函数
用const修饰的对象称为常对象,用const修饰的类的成员函数称为常函数,在常函数中不允许对任何变量进行修改,而通过常对象只能调用该对象的常函数
常函数和常对象的使用实例如下:
#include <iostream>
using namespace std;
class Test
{
public:
const int num = 10;
int val = 6;
void set_num_val() const
{
cout << "Hello World!" << endl;
cout << "The num is:" << this->num << "\n The val is:" << this->val <<endl;
//this->val = 7;
//this->num = 8;
}
void setNumVal()
{
this->val = 7;
//this->num = 8;
cout << "The num is:" << this->num << "\nThe val is:" << this->val <<endl;
}
};
int main()
{
Test *test = new Test();
const Test *testConst = new Test();
test->set_num_val();
test->setNumVal();
//testConst->setNumVal();
testConst->set_num_val();
return 0;
}
如上图所示,如果以上的语句没有注释,则在编译时将出现报错
注意:
- const修饰成员函数需要将const的位置写到函数声明的最后,即如下所示:
void func() const{}
- 如果函数定义和声明分开,则定义和声明时都需要写const关键字
- 如果一个常函数和一个普通函数的函数名、函数列表完全相同,则它们之间构成重载关系
- 常对象被创建之后,其成员值就不能被修改
3.const修饰函数参数和返回值
使用const修饰函数参数和返回值主要是让编译器为程序员做变量只读性检查,其使用时需要注意的地方如下:
- 用const修饰函数的参数时,主要将被引用对象或被指向的对象声明为常量,而不是将传值调用的形参声明为常量,因为这样没有意义(形参改变并不会影响实参)
- 当函数的返回值是一个普通数据而非引用时,用const修饰返回值的意义也不大(此时函数返回值为非左值,本身就不能改变其值)
4.常见的使用const的误解
- 用const修饰的值一定是不能改变的
- 常引用或常指针只能指向常变量