const总结

来源:互联网 发布:淘宝开店不能电脑认证 编辑:程序博客网 时间:2024/04/30 01:05

首先说明一下使用const的好处:
使用const的好处在于它允许指定一种语意上的约束------某种对象不能被修改--------编译器具体来实施这种约束。通过const,你可以通知编译器和其他程序员某个值要保持不变。只要是这种情况,你就要明确地使用const ,因为这样做就可以借助编译器的帮助确保这种约束不被破坏。
(一)
首先解释一下const与指针的关系:
const在指针的声明中有一下三种形式:
const char *p        = "hello";          // 非const指针,
                                         // const数据,就是说p指向的那个内存空间的数据是不可变的,但p还可以指向新的内存地址。

char * const p       = "hello";          // const指针,
                                         // 非const数据,就是说这个指针p一旦赋值或初始化,就不能在指向其他位置了,但其指向的位置的数据值是可变的。

const char * const p = "hello";          // const指针,
                                         // const数据,这个就很明显了,集上述两家之长处(也可能是短处哦,),上述两者都不可变。
一般来说,你可以在头脑里画一条垂直线穿过指针声明中的星号(*)位置,如果const出现在线的左边,指针指向的数据为常量;如果const出现在线的右边,指针本身为常量;如果const在线的两边都出现,二者都是常量。

恩,差点忘了,还有一种形式:
char const * p = "hello"; 
这其实与上边的情形一是一样的,只是由于个人习惯的不同,二者都是对的。

(二)
在一个函数声明中,const可以指的是函数的返回值,或某个参数;对于成员函数,还可以指的是整个函数。
const(1) int fun(int  const(2)& )const(3)
{
       int temp;
       retrun temp;
}
参数的 const属性(上例2处)一般用引用传递,是为了保证该参数在函数中不允许被修改,一旦修改,编译器会报错。

而返回值的const属性(上例1处)是保证函数的返回值不被修改,也许你会质疑这种可能性,但是这种可能性确实存在,
详细情形如下:(摘自effective c++)
const rational operator*(const rational& lhs,
                         const rational& rhs);

很多程序员第一眼看到它会纳闷:为什么operator*的返回结果是一个const对象?因为如果不是这样,用户就可以做下面这样的坏事:

rational a, b, c;

...

(a * b) = c;      // 对a*b的结果赋值

我不知道为什么有些程序员会想到对两个数的运算结果直接赋值,但我却知道:如果a,b和c是固定类型,这样做显然是不合法的。一个好的用户自定义类型的特征是,它会避免那种没道理的与固定类型不兼容的行为。对我来说,对两个数的运算结果赋值是非常没道理的。声明operator*的返回值为const可以防止这种情况,所以这样做才是正确的。

呵呵,象Scott Meyers这样的大师见地就是不一般吧

接下来说明函数的const属性:(上例3处)
当然喽,一般用于成员函数了,它有以下属性:
(1)const成员函数不被允许修改它所在对象的任何一个数据成员。
(2)const成员函数能够访问const对象的成员,而其他成员函数不可以。

(三)尽量使用 const代替define 吧,因为const是类型安全的。
应该使用
const double  pi = 3.1415926;
而不要用#define pi 3.1415926
后者是宏,仅仅是对程序中的pi用3.1415926代替,会让你对于一些编译时的错误很难定位。


C++常类型(const) 
 

常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。因此,定义或说明常类型时必须进行初始化。

一般常量和对象常量

1. 一般常量

一般常量是指简单类型的常量。这种常量在定义时,修饰符const可以用在类型说明符前,也可以用在类型说明符后。如:

int const x=2;



const int x=2;

定义或说明一个常数组可采用如下格式:

<类型说明符> const <数组名>[<大小>]…

或者

const <类型说明符> <数组名>[<大小>]…

例如:

int const a[5]={1, 2, 3, 4, 5};

2. 常对象

常对象是指对象常量,定义格式如下:

<类名> const <对象名>

或者

const <类名> <对象名>

定义常对象时,同样要进行初始化,并且该对象不能再被更新,修饰符const可以放在类名后面,也可以放在类名前面。

常指针和常引用

1. 常指针

使用const修饰指针时,由于const的位置不同,而含意不同。下面举两个例子,说明它们的区别。

下面定义的一个指向字符串的常量指针:

char * const prt1 = stringprt1;

其中,ptr1是一个常量指针。因此,下面赋值是非法的。

ptr1 = stringprt2;

而下面的赋值是合法的:

*ptr1 = "m";

因为指针ptr1所指向的变量是可以更新的,不可更新的是常量指针ptr1所指的方向(别的字符串)。

下面定义了一个指向字符串常量的指针:

const * ptr2 = stringprt1;

其中,ptr2是一个指向字符串常量的指针。ptr2所指向的字符串不能更新的,而ptr2是可以更新的。因此,

*ptr2 = "x";

是非法的,而:

ptr2 = stringptr2;

是合法的。

所以,在使用const修饰指针时,应该注意const的位置。定义一个指向字符串的指针常量和定义一个指向字符串常量的指针时,const修饰符的位置不同,前者const放在*和指针名之间,后者const放在类型说明符前。

2. 常引用

使用const修饰符也可以说明引用,被说明的引用为常引用,该引用所引用的对象不能被更新。其定义格式如下:

const <类型说明符> & <引用名>

例如:

const double & v;

在实际应用中,常指针和常引用往往用来作函数的形参,这样的参数称为常参数。

在C++面向对象的程序设计中,指针和引用使用得较多,其中使用const修饰的常指针和常引用用得更多。使用常参数则表明该函数不会更新某个参数所指向或所引用的对象,这样,在参数传递过程中就不需要执行拷贝初始化构造函数,这将会改善程序的运行效率。

下面举一例子说明常指针作函数参数的作法。

#include 
const int N = 6;
void print(const int *p, int n);

void main()
{
int array[N];
for (int i=0; i cin>>array[i];
print(array, N);
}

void print(const int *p, int n)
{
cout<<"{"<<*p;
for (int i=1; i cout<<","<<*(p+i);
cout<<"}"< }
 

常成员函数

使用const关键字进行说明的成员函数,称为常成员函数。只有常成员函数才有资格操作常量或常对象,没有使用const关键字说明的成员函数不能用来操作常对象。常成员函数说明格式如下:

<类型说明符> <函数名> (<参数表>) const;

其中,const是加在函数说明后面的类型修饰符,它是函数类型的一个组成部分,因此,在函数实现部分也要带const关键字。下面举一例子说明常成员函数的特征。

#include 
class R
{
public:
R(int r1, int r2) { R1=r1; R2=r2; }
void print();
void print() const;
private:
int R1, R2;
};

void R::print()
{
cout< }

void R::print() const
{
cout< }

void main()
{
R a(5, 4);
a.print();
const R b(20, 52);
b.print();
}
 

该例子的输出结果为:

5,4
20;52

该程序的类声明了两个成员函数,其类型是不同的(其实就是重载成员函数)。有带const

 
原创粉丝点击