时间:2022-09-07 09:57:29 | 栏目:C代码 | 点击:次
先看一个典型的程序:
#include<iostream> using namespace std; int main() { int num = 1; #define t1 num + num #define t2 t1 % t1 cout << "t2 is " << t2 << endl; // t2 is 2 const int s1 = num + num; const int s2 = s1 % s1; cout << "s2 is " << s2 << endl; // s2 is 0 return 0; }
运行结果如注释所示,分别得到“t2 is 2”、“s2 is 0”???
分析原因:const定义的常量s1、s2,则s1的值是num+num,s2的值是s1%s1,所以最后结果为“s2 is 0”;而define定义的变量作替换后,C++把cout<<"t2 is "<<t2<<endl;语句译成了:cout<<"t2 is "<<num+num%num+num<<endl;所以结果为“t2 is 2”(1+0+1=2)
注意:define定义的内容,建议增加使用括号()
#define t1 (num + num) #define t2 (t1 % t1)
具体分析define与const的区别,如下定义:
const float PI = 3.14; #define PI (3.14)
const约束对象的访问性质:使得对象只能读,不能写:不允许修改对象的值.
const 是constant 的缩写,“恒定不变”的意思。被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。所以很多C++程序设计书籍建议:“Use const whenever you need”。
const int n=5; int const n=5;
这两种写法是一样的,都是表示变量n的值不能被改变了,需要注意的是,用const修饰变量时,一定要给变脸初始化,否则之后就不能再进行赋值了。
// C const int num = 100; (int *)&num = 4; //可以间接修改
C的const表示修饰只读变量,但是我们可以恶意强制操作const对象。
接下来看看const用于修饰常量静态字符串,例如:
const char* str="fdsafdsa";
如果没有const的修饰,我们可能会在后面有意无意的写str[4]=’x’这样的语句,这样会导致对只读内存区域的赋值,然后程序会立刻异常终止。有了const,这个错误就能在程序被编译的时候就立即检查出来,这就是const的好处。让逻辑错误在编译期被发现。
如下修改都是不允许的。
// c++ const int i = 0; //是一个右值,有内存实体 i = 11; //错误:向只读变量‘i'赋值 const int a{1.1}; //错误:从“double”转换到“int”需要收缩转换,请初始化成相同类型的常量
常量指针是指针指向的内容是常量,可以有一下两种定义方式。
const int * n; int const * n;
需要注意的是一下两点:
1、常量指针说的是不能通过这个指针改变变量的值,但是还是可以通过其他的引用来改变变量的值的。
int a=5; const int* n=&a; a=6;
指针常量是指指针本身是个常量,不能在指向其他的地址,写法如下:
int *const n;
需要注意的是,指针常量指向的地址不能改变,但是地址中保存的数值是可以改变的,可以通过其他指向改地址的指针来修改。
int a=5; int *p=&a; int* const n=&a; *p=8;
注意:区分常量指针和指针常量的关键就在于星号的位置,我们以星号为分界线,如果const在星号的左边,则为常量指针,如果const在星号的右边则为指针常量。如果我们将星号读作‘指针’,将const读作‘常量’的话,内容正好符合。int const * n;是常量指针,int *const n;是指针常量。
指向常量的常指针
是以上两种的结合,指针指向的位置不能改变并且也不能通过这个指针改变变量的值,但是依然可以通过其他的普通指针改变变量的值。
const int* const p;
根据常量指针与指针常量,const修饰函数的参数也是分为三种情况。
1、防止修改指针指向的内容
void StringCopy(char *strDestination, const char *strSource);
其中 strSource 是输入参数,strDestination 是输出参数。给 strSource 加上 const 修饰后,如果函数体内的语句试图改动 strSource 的内容,编译器将指出错误。
2、防止修改指针指向的地址
void swap ( int * const p1 , int * const p2 )
指针p1和指针p2指向的地址都不能修改。
3、以上两种的结合。
如果给以“指针传递”方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。
例如函数:
const char * GetString(void);
如下语句将出现编译错误:
char *str = GetString();
正确的用法是
const char *str = GetString();
全局变量的作用域是整个文件,我们应该尽量避免使用全局变量,因为一旦有一个函数改变了全局变量的值,它也会影响到其他引用这个变量的函数,导致除了bug后很难发现,如果一定要用全局变量,我们应该尽量的使用const修饰符进行修饰,这样防止不必要的人为修改,使用的方法与局部变量是相同的。