用法:
(1)数据类型(int、char....)对于const而言是透明的。(const修饰它的直接右边,不能做左值)
如:
(const int SIZE =10;)等同于(int const SIZE =10;)
(const int * p=&a;)等同于(int const *p=&a;)
const int *p1=&a; //只读*p1,将p1的解引用“锁死”
int const *p2=&a; //只读*p2,将p2的解引用“锁死”(等同于1.)
int *const p3=&a; //只读p3,将p3的值“锁死”
const int const *p4=&a; // 只读*p4,将p4的解引用“锁死”(等同1.2.)
const int * const p5=&a; //只读p5和*p5,将p5的值、p5的解引用都“锁死”
int const *const p6=&a; //只读p6和*p6,将p6的值、p6的解引用都“锁死”(等同5.)
const在C和C++的不同:
C语言中:
const修饰的变量为常变量。只是在编译期间检查常变量有没有做左值,其他处理和变量一样。
const int a;
int* p = &a;
*p = 20;
printf("%d\n", a);//C语言中语法正确,打印a的值为20;
C++中:
const修饰的变量为常量。在编译期间把用到常量的地方替换为常量的初始值。
const int a = 10;
int* p = (int*)&a;
*p = 20;
std::cout << a << std::endl;//C++中语法正确,打印a的值为10(编译期间a已经替换为10)
在C++中使用const注意事项:
(1)一定要初始化(编译期间无法替换,编译错误);
(2)不允许常量做左值;
(3)不允许间接修改,杜绝间接访问来修改常量风险 ;
const int a = 10;
a = 20;//error,a已经替换为10,翻译过来 10 = 20;
int* p = &a;//error,存在p指针解引用修改a的值
(4)修饰全局变量时,会发生改变;
const int gdata = 20;
其作用域为此文件,编译器经过类型检查后直接用20在编译时替换gdata;
extend const int gdata2 = 20;
将const改为外部连接,作用于扩大至全局,编译时会分配内存,并且可以不进行初始化,仅仅作为声明,编译器认为在程序其他地方进行了定义。
(5)const修饰函数
class Test
{
public:
Test(int a) :ma(a){}
void Show()
{
std::cout << "ma:" << ma << std::endl;
}
private:
int ma;
};
int main()
{
const Test test(20);//常对象
test.Show();//error,Test* const this ==> const Test* const this
/*
const Test test(20);
const Test* const this = &test;
*/
}
因为对象调用成员方法默认是_thiscall调用约定,this指针的类型为Teat * const ;而常对象是不允许修改的,所以必须const Test* const 类型的指针才能访问其成员。
与宏定义(define)比较:可以节省节省空间,避免不必要的内存分配。
#define Max1 100 //常量宏
const double Max2=100; //此时并未将Max2放入RAM中
double de1=Max1; //编译期间进行宏替换,分配内存
double co1=Max2; //此时为Pi分配内存,以后不再分配
double de2=Max1; //在进行宏替换,再次分配内存
double co2=Max2; //没有分配内存
与静态变量(static)比较:
(1)存储方式不同:
const定义的常量在超出其作用域之后其空间会被释放,const变量的值不能修改;
而static定义的静态常量在函数执行后不会释放其存储空间,static变量的值可以修改。
(2)static多用于修饰函数,规定此变量这能在该模块(文件)使用。