C++指针与引用:const修饰的奥秘
目录
1. 修饰指针
1.1 const在*之后
1.2 const在*之前
2.修饰引用
2.1 常引用
3.修饰函数参数
4.修饰成员函数
1. 修饰指针
1.1 const在*之后
int a = 10;
int* const p = &a;
const在*之后这个表明了指针p是一个常量,就是p的值一旦被确定了就不能在修改了。
p的值一旦被确定了就不能被修改是什么意思?说成人话就是p的指向不能发生改变。如果我们改变p的指向编译器就会报错。
我们想把p的指向改成b,但是报错了,这就说明了const在*右边指针的指向是不能被改变。但是我们可以修改p所指向变量的内容。
我们通过p把a的值改成了100说明,p所指向对的内容是可以修改的.
1.2 const在*之前
int a = 10;
const int* p = &a;(或者 int const* p = &a)
const在*左边修饰的是*p, 就是说明*p不能被修改
我们通过报错可以知道,这个时候*p是常变量,也就是说const在*左边的时候我们不能通过指针去修改原来变量的值.
我们不能够修改*p的值,但是我们可以修改p的指向,这是可以的。
int b = 10;
p = &b;
2.修饰引用
2.1 常引用
int a = 10;
int& pa = a;
我们通过pa可以修改a,但是如果我们在pa前加上const那么pa的值就不能被修改。
我们知道引用是变量的别名,但是这样为什么会报错呢?
int& p = 1;
我们知道引用是变量的别名,通过修改引用就能够修改原变量的值,但是这里有一个问题就是
10 是一个常量值是不能被修改的,也就是说如果我们向上面这样写是不行的。那么我们应该怎么样去解决这个问题呢?我们可以在前面加上const这样就不会报错了。
const int& p = 1;
这里涉及到一个问题,是关于权限的问题,这里大家一定要记住,权限可以缩小和平移,但是不能放大.
上面这个例子,就是权限放大的造成的.10是常量大小不能改变,p引用可以改变大小,造成权限放大。
权限平移:a和pa都属于常变量属于权限平移
const int a = 10;
const int& pa = a;
权限缩小:a属于变量,但是pa属于常变量,属于权限缩小
int a = 10;
const int& pa = a;
3.修饰函数参数
void my_strcpy(char* des , char* src ) {while ((*des++ = *src++));
}
int main() {char str[] = "hello world";char str1[12] = {0};my_strcpy(str1, str);return 0;
}
我们想要写一个函数去完成字符串的拷贝,但是这里有一个问题,我们在写这个函数的时候
我们把*des++ = *src ++ 写成 *src ++ = *des++这个时候就会出现问题.所以我们可以在src前面加上const,这个时候如果我们不小心写法这个赋值编译器就会报错。
void my_strcpy(char* des , const char* src ) {while ((*des++ = *src++));
}
如果我们写返了,编译器会给报错不能给常量赋值,因为加上const之后是不能修改的,所以我们在写函数参数的时候,如果不想参数被修改就加上const修饰参数.
4.修饰成员函数
class A {
public:void Print() {cout << _a << " " << _b << endl;}
private:int _a = 1;int _b = 1;
};void print(const A& a) {a.Print();
}int main() {A a;print(a);return 0;
}
为什么上面这个代码会报错呢?这里a调用Print其是隐式调用,真实的调用其是把a的地址传过去,而Print里面有一个隐式的this指针作为参数,这些都是编译器做的处理不会显示出来.
a.Print(&a);
void Print(A* const this);
这里的a是const类型,而Print中的this指针const修饰的是指针本身,就是this指针的指向不可以发生改变,但是指针的内容可以发生改变.这里发生了权限放大的问题,所以编译器会报错.
这个时候,如果我们就想a调用Print怎么办?这个时候我们的const就派上用场了.
void Print() const {
cout << _a << " " << _b << endl;
}
我们在Print的参数列表后面加上const后我们就可以成功调用了.就算不是const类型也可调用.
加上const指针后,Print中的隐式this指针的类型就会变成
const A* const this
这个时候我们this指针的指向不能发生改变,还有所指向的内容也不能发生改变.