零、前言
关于const,目前让我对这个知识点分类,我会分为:c语言中的const;c++中的const、c++中类的成员函数的const
一、C语言中的const
1.c语言中,const修饰的是常变量;常变量只有一个特点:不可以做左值。也就是不可以放在等号左边。想了一下,不做左值这是一条语法规则,在编译时期检查出,所以但凡放在=左,编译器就会报错。如图:
其他特性和普通变量一样。所以,c语言中的conse修饰的变量,是可以被改变的。
代码如上图:并且我将文件名改为.c,这是一个简单的c文件
#include<stdio.h>
int main()
{
const int a = 10; //常变量a为10
int *p = (int*)&a; //取a的地址将其强转为int* ,然后赋值给指针p
*p = 20; //改变p所指向的地址的值,也就是解引用改变a的值
printf("a = %d\n",a);
printf("*p = %d\n",*p);
return 0;
}
c语言中的强转真是一个暴力转换,能消除常性),将const int* -> int* 。这一点真是让我大吃一惊。
查看运行结果:
发现a的值被改变。
二、c++中的const
1.对比c语言中的const
c++中const修饰的是常量。何为常量:就是不可以更改的。
有如下3个性质:
1.常量要初始化(因为不可修改,所以没有初始值就没有意义)
2.不能做左值
3.不能间接修改,杜绝间接访问修改风险
但是,我们还是可以通过暴力手段,强行试着改变一下:还是上述代码,我将文件名后缀由.c改变为.cpp
查看运行结果:
结论:c++中,在用到常量的地方 替换成 该常量初始化的值。
在程序要打印a的时候,代码已经被替换成:printf("a = %d\n",10); 不由想起了宏替换。
说下我的理解,不是咱const不够牛逼,实在是这句强转int* p = (int*)&a; 太无赖了!道高一尺魔高一丈,强转是真够暴力,强转前需要深思。
2.const的几种使用辨析
在const修饰指针时,确实会有多种写法,写法不同产生的意义不同。之前c和c++的区别中,总结过笔记:
再次强调:
我理解的const:修饰最近的一个已经成型的类型,修饰什么,什么不可改变。
例1:
const int * p = &a;
int const * p = &a;
这两句代码,const都修饰int,int是已经成型的类型,修饰int即就是这个值,所以p的指向可以改变,*p则不可以(*p可能带来修改的风险)。
例2:
int* const p = &a;
const修饰int* ,修饰指针,则p的指向不可以改变,但*p = 323;是可以的,所指向的值是可以改变的。
例3:二者都添加const
const int* const p = &a;
p的指向不可以改变 并且 p所指地址存放的值也不可以改变。
2.5 effective c++中是这样辨析const
下面几句代码的注释很有意思:
const pointer,const data:const即修饰指针也修饰数据
const data ,non-const pointer:const修饰数据,没修饰指针
看到effective c++中,和我说的“const修饰离它最近的已成型的类型”有差别,虽然说法不同,但结果相同。怎么理解,自己理解就好,不必过多纠结。
3.c、c++中const修饰的全局变量的区别:
c中:
const修饰的全局变量:属性为global
c++中:
const修饰的全局变量:属性为local即本文本可见 外部访问需加extern
4.const修饰class中的成员函数 以及 自定义类的常对象
(1)常对象:里的成员变量都具有常属性。
(2)常对象不能访问普通函数,只能访问const修饰的成员函数。
因为对象调用函数(或者说函数依赖于对象调用),类的成员函数如何知道它被哪一个对象调用呢?答曰:this指针
对象调用成员函数时,默认第一个参数是this指针,this指针指向对象的地址;this指针的类型为:classname* const this;
也就是说this指针是加了const属性的,const只是修饰的指针的指向,指向不可以改变,但是所指的内容是可以改变的。
但是,常对象的this指针的类型为:const classname* const this ,const即修饰指向也修饰所指的内容。
现有如下代码:
class Test
{
public:
Test(int a) :ma(a){}
void Show()//const //const Test* const this = &test; //Test* const ==> const Test* const
{
std::cout << "ma:" << ma << std::endl;
}
public:
int ma;
};
int main()
{
const Test test(20);
test.Show();
return 0;
}
对象test的地址:&test = const Test* const this,show函数中的this指针类型为:Test* const this
现在要将一个级别高(const修饰权限高)的指针赋值给一个权限低的,降低权限,就相当于低权限指针修改了高权限的值,那必然是不对的。
所以,const常对象不能访问普通函数,只能访问const成员函数。
5.const修饰迭代器
迭代器在某种角度上可以当做指针看待,这样的话就可以用const修饰,即const iterator it,但迭代器中还有一个const_itreator的类型(迭代器所指数据博客改变),二者就有差别了。
第一次看很晕,不过后来再理解,很容易:
const iterator iter;//const修饰指向
const_iterator iter; //iter所指之物是const