const单词字面意思为常数,不变的。它是c/c++中的一个关键字,是一个限定符,它用来限定一个变量不允许改变,它将一个对象转换成一个常量。
C语言中的const
C语言中的const修饰变量实际上只是一个只读变量,并不是实际意义上的常量,局部const存储在堆栈区
像下面这段代码,虽说声明了const ,但是也可以通过指针来间接修改值
void main()
{
const int a = 10;
int *p = (int *)&a;
*p = 100;
printf("%d\n", a);
system("pause");
}
当然,如果在函数外面定义的全局的const会被存储到只读数据段,受到只读数据段的保护,不可以修改,所以即使编译通过了,在运行期,修改a的值时,发生写入错误。原因是修改只读数据段的数据。
const修饰的变量在C语言中是外部链接的,可以在整个项目中的所有文件都可以使用,所以要注意重定义问题
因为是一个只读变量,在C语言中,const总是需要一段内存空间,所以无论是在函数内部定义还是在函数外部定义的都不可以用来定义数组
const int a = 10;
void main()
{
int *p = (int *)&a;
*p = 100;
int arr[a];//err
printf("%d\n", a);
system("pause");
}
C++中的const
在C++中,一个const不必创建内存空间(在c++中,是否为const常量分配内存空间依赖于如何使用。一般说来,如果一个const仅仅用来把一个名字用一个值代替(就像使用#define一样),那么该存储局空间就不必创建。) 但对const取地址会分配内存
对于基础数据类型,也就是const int a = 10这种,编译器会把它放到符号表中,不分配内存,当对其取地址时,会分配内存。
void main()
{
const int a = 10;
int *p = (int *)&a;
*p = 100;
cout << "a = " << a << endl;
cout << "*p = " << *p << endl;
system("pause");
}
运行结果是:
结果显示a并没有修改,原因在于a是在符号表中,当对a取地址时,会为a分配一个新空间,而*p操作的是分配的新空间,而值是从符号表获取的
如果上面那句话没有听懂的话,我们在来详细说一下,其实就相当于我们对a取地址的时候,编译器会创建一个临时的变量从符号表接受a的值,然后把这个临时变量的地址传给p,*p操作的就是这个新的变量的空间,所以*p再怎么改变,也改变不了a的值
对于基础数据类型,如果用一个变量初始化一个const变量(const int a = b;),那么也会给a分配内存
void main()
{
int b = 10;
const int a = b;
int *p = (int *)&a;
*p = 100;
cout << "a = " << a << endl;
cout << "*p = " << *p << endl;
system("pause");
}
运行结果是:
由结果我们可以发现,a的值改变了,由此可见,只要分配了内存的const,我们就可以设法改变它的值
还有一种情况
如果是自定义数据类型,那么也会分配内存
#include <iostream>
using namespace std;
class Person
{
public:
int age;
};
void main()
{
const Person person;
//person.age = 10; err:不可以修改
Person *per = (Person *)&person;
per->age = 100;
cout << "per->age = " << per->age << endl;
per->age = 200;
cout << "per->age = " << per->age << endl;
system("pause");
}
运行结果是:
由此可见,确实改变了
const在C++中是内部链接的,也就是只能当前文件使用,如果想让其在文件外(即别的文件)使用,要在const前加上extern显示声明一下(extern const int a = 10;)
总体而言,在C++中的const更好一些
还有一个地方是关于引用的,如果引用一个常量是不可以的(int &ref = 10; //err),因为10是常量,没有内存,如果在前面加上const就不一样了,const int &ref = 10 ;这样就可以编译通过了,因为编译器为其分配了内存,原理和上面的那个符号表问题一样
这样的引用常用于做函数形参,用来限定不可修改,防止不小心修改了数据
C语言和C++中const和指针的关系是一样的:
const int *a; //不可以修改a指向的内存空间,但可以改变a 的指向,让它指向别的变量(只读,可以改变指向)
int const *a; //意思和上面的一样
int *const a; //不可以修改a的指向,但可以操作a指向的内存空间(不可以改变指向,可读可写)
const int *const a; //不可以修改a的指向,也不可以操作a指向的内存空间(不可改变指向,只读)
关键在于*,const在*左边,修饰的是变量,即变量不可修改;const在*右边,修饰的是指针,即指针不可修改。
这也就是所谓的常量指针和指针常量
(个人整理,或许不够全面,如果有不正确的地方,欢迎指正,代码在VS编译器上测试)