首页 > 代码库 > 详解C和C++中的const关键字

详解C和C++中的const关键字

在讲下面的内容之前,要先看看这篇文章const、static变量的存储位置

一、C中的const

作用:(1)可以定义const常量,具有不可变性。

      (2)便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。

      (3)可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。 同宏定义一样,可以做到不变则已,一变都变!

      (4)可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。 还是上面的例子,如果在函数体内修改了i,编译器就会报错;

      (5) 可以节省空间,避免不必要的内存分配。 例如:

       #define PI 3.14159 //常量宏
     const double Pi=3.14159; //此时并未将Pi放入RAM中 ......
     double i=Pi; //此时为Pi分配内存,以后不再分配!
     double I=PI; //编译期间进行宏替换,分配内存
     double j=Pi; //没有内存分配
     double J=PI; //再进行宏替换,又一次分配内存!

     const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。

const变量与常量的区别

C中const变量是由编译器指定的只读数据,存储在只读数据区,但它不是常量,虽然常量也存储在只读数据区,所以不能由它来指定数组的长度。例如下面的是不允许的:

const int n = 5;
int a[n];//编译器将会报错
注意:在C++中定义的变量也是常量,上述用法是合理的。
②const限定变量的方式
const使用的基本形式: const type m;限定m不可变。看下面的例子:
typedef char * pStr;
char string[4] = "bbc";
const char *p1 =" string"; //1式
const pStr p2 =" string"; //2式
p1++;
p2++;//不允许
替换基本形式中的m为1式中的*p1,替换后const char *p1;限定*p1不可变,当然p1是可变的,因此问题中p1++是对的。替换基本形式中的type为2式中的pStr,替换后const pStr m;限定m不可变,题中的pStr就是一种新类型,因此问题中p2不可变,p2++是错误的

二、C++中的const

以上所讲内容在C++中同样适用,另外在C++中const经常用来限定成员函数类型,使其成为常成员函数。const成员函数应该在函数原型说明和函数定义中都增加const限定。

<pre class="cpp" name="code">#include<iostream>
using namespace std;
//const int Y;
class C
{
	const int X;
	int M;
public:
	C(int a = 0,int b = 0):X(a),M(b){}
	int Get() const
	{
		return X;
	}
	//void Set() 
	//{
	//	X = 5;
	//}
	int GetX()
	{
		return X;
	}
	//void SetX(int X)
	//{
	//	this->X=X;
	//}
};
void main()
{
	const C constC(5);
	C c;
	cout << constC.Get();
	cout << c.Get();
	cout << c.GetX();
	//cout << constC.GetX();
}

①非常量成员函数不能被常量成员对象调用,因为它可能企图修改常量的数据成员,所以constC.GetX()将会产生错误。

②常量成员函数定义里面不能修改成员变量的值,所以C::Set()成员函数将会产生错误。

我们定义的类的成员函数中,常常有一些成员函数不改变类的数据成员,也就是说,这些函数是"只读"函数,而有一些函数要修改类数据成员的值。如果把不改变数据成员的函数都加上const关键字进行标识,显然,可提高程序的可读性。其实,它还能提高程序的可靠性,已定义成const的成员函数,一旦企图修改数据成员的值,则编译器按错误处理。

为了确保const对象的数据成员不会被改变,在C++中,const对象只能调用const成员函数。如果一个成员函数实际上没有对数据成员作任何形式的修改,但是它没有被const关键字限定的,也不能被常量对象调用。

③但构造函数和析构函数对这个规则例外,它们从不定义为常量成员,但可被常量对象调用(被自动调用),它们也能给常量的数据成员赋值。

注:在类中声明的const变量可以不用初始化,但是在其他情况下必须初始化。