1、const修饰指针变量
左定值,右定向,const修饰不变量。
const 修饰指针变量有以下三种情况。
-
A: const 修饰指针指向的内容,则内容为不可变量。
-
B: const 修饰指针,则指针为不可变量。
-
C: const 修饰指针和指针指向的内容,则指针和指针指向的内容都为不可变量。
对于 A:
const int *p = 8;
则指针指向的内容 8 不可改变。简称左定值,因为 const 位于 * 号的左边。
对于 B:
int a = 8;
int* const p = &a;
*p = 9; // 正确
int b = 7;
p = &b; // 错误
对于 const 指针 p 其指向的内存地址不能够被改变,但其内容可以改变。简称,右定向。因为 const 位于 * 号的右边。
对于C:则是 A 和 B的合并
int a = 8;
const int * const p = &a;
这时,const p 的指向的内容和指向的内存地址都已固定,不可改变。
对于 A,B,C 三种情况,根据 const 位于 * 号的位置不同,我总结三句话便于记忆的话:"左定值,右定向,const修饰不变量"。
类型 | 写法(以int 为例) | 含义 | 能否改指针? | 能否改数据? |
---|---|---|---|---|
指针常量 | int *const a = &b; | 指针本身是常量 | ❌ 否 | ✅ 是 |
常量指针 | const int *a = &b; | 指针指向的数据是常量 | ✅ 是 | ❌ 否 |
2、const修饰类成员函数
const 修饰类成员函数,其目的是防止成员函数修改被调用对象的值。
注意:const 关键字不能与 static 关键字同时使用,因为 static 关键字修饰静态成员函数,静态成员函数不含有 this 指针,即不能实例化,const 成员函数必须具体到某一实例。
下面的 GetX()const; 函数用到了 const 成员函数:
#include <iostream>
#include <string>
class Entity
{
private:
int m_X,m_Y;
mutable int var;//mutable允许函数是常量方法,但可以修改变量
public:
int GetX() const
{
var = 2;
return m_X;
}
void SetX(int x)
{
m_X = x;
}
};
void PrintEntity(const Entity& e)
{
std::cout << e.GetX() << std::endl;
}
int main()
{
Entity e;
std::cin.get();
}
同时,在这个例子中,const还修饰了PrintEntity函数参数,参数是我们自定义的类型。
自定义类型的参数传递,需要临时对象复制参数,对于临时对象的构造,需要调用构造函数,比较浪费时间,因此我们采取 const 外加引用传递的方法。
如果 GetX() 去掉 const 修饰,则 PrintEntity 传递的 const e 即使没有改变对象的值,编译器也认为函数会改变对象的值,所以我们尽量按照要求将所有的不需要改变对象内容的函数都作为 const 成员函数。
如果有个成员函数想修改对象中的某一个成员怎么办?这时我们可以使用 mutable 关键字修饰这个成员,mutable 的意思也是易变的,容易改变的意思,被 mutable 关键字修饰的成员可以处于不断变化中,如例子中的 mutable int var; 。
看const的作用,首先看const左边的内容,左边没有再看右边。
举例: const int* const getX() const{} 第一个const左边没有,看右边和int绑定在一起,说明不能改变指针指向的值。第二个const 左边是int*,相当于和地址绑定在一起,说明不能改变指针的值(即地址),第三个const左边是getX函数名,说明不能改变函数里面的东西,这个函数是只读的。