您的位置:首页 > 编程语言 > C语言/C++

c++中const类型的使用与注意事项

2013-02-26 18:09 381 查看
常量是标识符他在程序运行期间是恒定不变的,在c语言中可以用#define来定义一个常量,称为宏常量。c++中除了宏常量还可以用const来定义常量。

常量为什么存在和存在的意义, 如果不使用常量,直接在程序中填写数字或字符串,将会有什么麻烦?

(1) 程序的可读性(可理解性)变差。程序员自己会忘记那些数字或字符串是什么意

思,用户则更加不知它们从何处来、表示什么。

(2) 在程序的很多地方输入同样的数字或字符串,难保不发生书写错误。

(3) 如果要修改数字或字符串,则会在很多地方改动,既麻烦又容易出错。

一、const修饰普通变量和指针变量

const 修饰变量有两种方式:

const TYPE value;

TYPE const value;

这两种写法本质上是相同的,对于一个非指针的类型TYPE,无论怎么写,都是一个含义,即value值不可变。

但是对于指针类型的TYPE,不同的写法会有不同情况:
(1)指针本身是常量不可变
(char*) const p;
(2)指针所指向的内容是常量不可变
const (char) *p;
(char) const *p;
(3)两者都不可变
const char* const p;

识别const到底是修饰指针还是指针所指的对象,还有一个较为简便的方法,也就是沿着*号划一条线:
如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。
二、const修饰函数参数
用const修饰函数的参数用途非常广泛,也使程序更安全更高效。被声明为const类型的变量在函数体内不容许被改变。
int function(const int val) // val在函数体内不容许改变
int function(const char* val) //val 所指向的内容在函数体内不容许改变
int function(char* const val) // 指针变量val本身是常量 在函数体内的指向不容许改变
int function(const class &val ) // 引用类型在函数体内不许改变
经常在函数传递阐述的时候会使用引用类型是因为,如果该类型是自定的不是系统自带的基本数据类型,如果函数采取的是非引用(值传递),函数会产生临时变量并赋值该变量的至这样影响了函数调用的效率,因此在函数参数传递的过程中经常采用的是传引用。
三、const修饰类对象、对象指针、对象引用

const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。
const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。
class A
{
public :
int func1();
int func2() const;
};

const A obj;
obj.func1();//error 不能调用非const函数
obj.func2();// ok

const A* obj;
obj->func1();//error
obj->func2();//ok
四、const修饰数据成员
const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么,例如:

class A

{

const int size = 100; //错误

int array[size]; //错误,未知的size

}

const数据成员的初始化只能在类的构造函数的初始化列表中进行。
class A
{
A(int size);
const int SIZE;
};
A::A(int size):SIZE(size)
{}
要想建立在整个类中都恒定的常量,可以用类中的枚举常量来实现,例如:

class A

{


  enum {size1=100, size2 = 200 };

  int array1[size1];

  int array2[size2];


}
枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。

五、const修饰成员函数

const修饰类的成员函数,用const修饰的成员函数不能改变对象的成员变量。一般把const写在成员函数的最后:

class A

{

int func() const;

};

对于const类对象/指针/引用,只能调用类的const成员函数。

六、const修饰成员函数的返回值

1、一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下:如果返回const对象,或返回const对象的引用,则返回值具有const属性,返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。

2、如果给采用“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针所指的内容)不能被修改,该返回值只能被赋给加const 修饰的同类型指针:

const char * GetString(void);

如下语句将出现编译错误:

char *str=GetString();

正确的用法是:

const char *str=GetString();

3、函数返回值采用“引用传递”的场合不多,这种方式一般只出现在类的赙值函数中,目的是为了实现链式表达。如:

class A

{


A &operate= (const A &other); //赋值函数

}

A a,b,c; //a,b,c为A的对象



a=b=c; //正常

(a=B)=c; //不正常,但是合法

若赋值函数的返回值加const修饰,那么该返回值的内容不允许修改,上例中a=b=c依然正确。(a=b)=c就不正确了。
还有在重载输入输出流操作符的时候也是这种情况<<, >>。

七 const常量与define宏定义的区别
l 编译器处理方式不同
define宏是在预处理阶段展开。
const常量是编译运行阶段使用。
l 类型和安全检查不同
define宏没有类型,不做任何类型检查,仅仅是展开。
const常量有具体的类型,在编译阶段会执行类型检查。
l 存储方式不同
define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。
const常量会在内存中分配(可以是堆中也可以是栈中)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: