本文主要是介绍C++略识 之关键字const,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1、const修饰的变量必须进行初始化
-->一般数据类型const常量初始化
const int i = 10; //合法
const int j; //非法,导致编译出错
-->指针const常量初始化
int *p = new int();
const int *p =q; //等价于 int const *p = q;
-->引用const常量初始化
int *p = new int();
const int *p =q; //等价于 int const *p = q;
[注意]:const常量有数据类型,而宏常量(#define)没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。
2、const限定符声明的的变量具有只读属性
const int i = 10;
int j = 0;
// to do ...
i = j; //非法,导致编译出错
j = i; //合法
3、const相比较于define,可以避免不必要的内存分配
#defineSTRING "abcdefghijklmn\n"
const charstring[]="abcdefghijklm\n";
...
printf(STRING); //为STRING分配了第一次内存
printf(string); //为string一次性分配了内存,以后不再分配
...
printf(STRING); //为STRING分配了第二次内存
printf(string);
...
由于const定义常量从汇编的角度来看,只是给出了对应的内存地址, 而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。
4、是不是const的常量值一定不可以被修改呢?
非也!!!
const int i=0;
int *p=(int*)&i;
p=100;
通过强制类型转换,将地址赋给变量,再作修改即可以改变const常量值。说明了申明为常量的数据也可能被改变。
我这里补充的是不要对const 的滥用。强制绕过const 检查可能会引起运行错误。
把const int i=0 声明在函数内,能够达到你的目的;把const int i=0 声明为全局变量,虽然仍然能够用强制转换绕过编译器检查,但会引起运行错误。
可参考下例:
const int j=50;
void main()
{ const int i=0; int *p=(int*)&i; *p=100; int *p2=(int *)&j; *p2=200; // runtime error cout << &i << &j; system("pause");
}
5、必须分清楚是数值常量还是指针常量
int j=0;
const int i=0; //i是常量,i的值不会被修改
const int *p1=&i; //指针p1所指内容是常量,可以不初始化
int * const p2=&j;//指针p2是常量,所指内容可修改
const int * const p3=&i; //指针p3是常量,所指内容也是常量
p1=&j; //不合法 左操作数包含“int *”类型
*p2=100; //不合法 右操作数包含“int *const ”类型
[注意]:指向常量的指针并不能保证所指向的值不被改变。比如:
const int i=10;
void main()
{ const int j=20; int k = 30; const int * p1=&i; const int * p2 = &j; const int * p3 = &k; // i=80; fail // j= 20; fail // *p3 = 50; fail // 以上三种均未逃过编译器检查 k=80; // succeed 逃过了编译器检查。 *p3 不行,但直接改k 允许。 system("pause");
}
6、const修饰类的数据成员
class A
{ const int size; //to do…
}
[注意]:const修饰的数据成员只在某个对象的生存周期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const修饰的数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么。比如:
class A
{ const int size = 100; //错误 int array[size]; //错误,未知的size
}
const数据成员的初始化只能在类的构造函数的初始化表中进行。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现。比如:
class A
{ //to do… enum { size1=100, size2 = 200 }; int array1[size1]; int array2[size2];
}
[注意]:枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。
7、const在函数声明中的应用
在一个函数声明中,const 可以修饰函数的返回值,或某个参数;对于成员函数,还可以修饰是整个函数,比如:
void fun1(const A *a );
const A fun2( );
void fun3( ) const; // fun3( )为某个类的成员函数
[注意]:调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,比如:
void fun1(const A *a); //不能对传递进来的指针的内容进行改变,保护了原指针所指向的内容
void fun2(const A &a); //不能对传递进来的引用对象进行改变,保护了原对象的属性<a target=_blank name="OLE_LINK2" style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></a>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><strong><span style="color: red;">[注意</span><span style="color: red;">]</span></strong></span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">:参数const通常用于参数为指针或引用的情况,且只能修饰输入参数;若输入参数采用“值传递”方式,由于函数将自动产生临时变量用于复制该参数,该参数本就不需要</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">保护,所以不用const修饰。</span>
[小结]:
--->对于非内部数据类型的输入参数,因该将“值传递”的方式改为“const引用传递”,目的是为了提高效率。例如,将void Func(A a)改为void Func(const A &a)。
--->对于内部数据类型的输入参数,不要将“值传递”的方式改为“const引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x)不应该改为void Func(const int&x)。
这篇关于C++略识 之关键字const的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!