Chinaunix首页 | 论坛 | 博客
  • 博客访问: 213159
  • 博文数量: 35
  • 博客积分: 1480
  • 博客等级: 上尉
  • 技术积分: 390
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-14 14:27
文章分类

全部博文(35)

文章存档

2008年(35)

我的朋友

分类: C/C++

2008-03-21 22:58:07

常 量

1.C++中是用const代替#define的,因为C中的#define有个细小的缺陷,它不能被编译器进行类型检查。

2.必须把const定义放进头文件里,这样,通过包含头文件,把const定义分配给一个编译单元,C++const是默认为内部连接的。也就是说const仅仅是在被定义过的文件里才是可见的,在连接时不能被其他编译单元看到,也就是说,如果有两个类引用了常量a ,而这两个类中的头文件中对a 赋予了不同的值,编译时,这两个a不会互相干扰。实际上,C++编译器并不会为const int aa 分配内存空间,仅仅当程序中遇到a时,就用常量折叠(把a的值代替a)的方法对程序进行处理。

3.如果用extern作了清楚的说明 extern const int bufsize.那么就必须强制进行存储空间分配(还有一种情况,如果要强制获取a的地址时也是要进行存储空间分配)

4.指向const的指针和const指针。

指向const的指针是指指针所指向的变量的值是不能被改变的,而指针本身可以被改变,const指针是指指针值是不能被改变的,而指针所指向的值是可以改变的。

Const int* u int const* u 都是表示指向const的指针

Int d=1;Int* const w=&d*w=2 表示const指针

这里面的int *中的 *实际是和变量结合的,不和类型结合,而且它可以被放在类型和变量之间的任何位置!

5C++对类型检查是非常精细的,可以把一格非const对象的地址赋给一个const指针,但是不可以把一个const对象的地址赋给一个非const指针,因为这样做可能通过被赋值的指针改变对象的值,当然总可以用强制类型转化进行这样的赋值,这是一个不好的设计习惯。

6Char* cp=”howdy”;虽然编译器不报错,可是实际这是一个错误,因为howdy是被编译为一个常量字符数组建立的,引用该字符数组只能得到内存的首地址,修改该字符数组内的任何字符都会导致运行时错误

7.如果将const修饰函数参数,该参数就不能被改变,所以在以值传递形式写的函数参数时,这个参数实际是函数创建者的工具,而不能体现函数调用者的作用,那么如何更体现函数调用者的职能呢?可以在函数内部用const修饰参数的一个拷贝,而将参数定义为非const

8.如果用const修饰函数返回值,这就约定了函数框架里的原变量不会被修改,另外,这个变量被制成了副本,使得初值不会被返回值所修改。

对于内部类型来说,按值返回得是否是一个const是无关紧要的,所以按值返回一个内部类型时,应该去掉const。当返回用户类型时,它不能是一个左值(即不能被修改和赋值)

有时候,编译器必须要创造临时对象,它们和其他对象一样需要构造和销毁,区别是我们从来都看不到它们,它们由编译器负责决定去留,但是它们会自动的成为常量,即已经用const修饰过。

9.在传递和返回地址时,在指向const的指针中,编译器不允许使用存储在const指针里的地址建立一个非const指针,是否选择返回一个指向const的指针或者引用,取决于想让客户程序员用它干什么。标准参数传递一般采用const  引用,因为一方面const规定了不能改变所引用的参数值,另一方面引用传递可以节约空间。而且const引用还可以接受一个临时变量(临时变量自动是const的)。

 

void tint*{}

void u(const int* cip){

//!*cip=2;//不能改变(指向const的指针)指向的值

//!int *ip2=cip;//不能申请普通指针来改变const

}

const char* v(){

//这里的返回是建立在堆空间中的,而非const的是建立在//栈空间中的,函数返回后,栈就被清除了

return “result of function v()”;

}

const int* const w(){

static int i;

return &i;

}

 

int main(){

int x=0;

int* ip=&x;

const int* cip=&x;

t(ip);//OK ,普通函数调用普通指针

//t(cip);//普通函数不能调用指向const的指针

u(ip);// const参数的函数可以调用指向const的指针

u(cip);// const参数的函数可以接收普通非const指针

//! char *cp=v();//和返回类型不匹配

const char* ccp=v();//和返回类型匹配

//! int* ip2=w();//和返回类型不匹配

const int* const ccip=w();和返回类型匹配

const int* cip2=w();//和返回类型不匹配,但是这里w()

//作为右值赋给左边时会产生临时变量,而临时变量是const的,原始变量不会被改变。

//! *w() =1;//Not OK

}///:~

 

10.类中的const用法,可以在类中申请const变量,但是这个变量必须优先于构造函数被创建,因为类申明时并没有实际创建对象,所以这个const的分配是在创建对象时先于构造函数被创建的,C++种采用一种初始化列表来给这些先于构造函数的赋值,也可以看作是内部类型的构造函数,所以类中const变量的值实际取决于构造函数中的初始化列表,也就是说,类的每个对象将有不同的const值,除非在申明const时加入了static修饰。而这个初始化列表的方法后来被拓展开来成为一种赋值方法,如

float pi(3.14)

11.在旧版本的C++中,并不支持static const,旧版本的解决办法是用五标记enum,如enum {Size=100};这样Size就被赋予了和static const一样的功能。

12.对象和成员函数也可以申明为const.对于const对象,它不能调用非const成员函数,因为非const成员函数有可能会改变对象中的值,但是仅仅在类里申明const成员函数对安全性还是不够的,因为在类外的成员函数中还是有方式改变类中成员的,所以编译器要求函数定义时要重申const说明,必须放在函数参书表的后面,一个const成员函数调用const和非const对象是安全的,不修改任何数据成员的任何函数都应该把它申明成const的,这样可以和const对象一起使用。

 

13const对象分为按位const和按逻辑const,按位const是比较严格的按字节固定,按逻辑const是保持对象从概念上的不变,但是可以以成员为单位而改变,一般默认的const对象是按位const的,要实现按逻辑const 属性,有两种又内部const成员函数改变数据成员的方法,一种方法已经过时,称为强制转换常量性,另一种是在类申明中使用关键字mutable,以指定一个特定的数据成员可以在一个const对象里被改变。

14.只读存储能力所需要的条件很严格,不仅要求对象是const的,要求是按位const,而且classstruct必须没有用户定义的构造函数和析构函数,不能有基类。不能包含由用户定义构造函数或析构函数的成员对象。

 

 

阅读(1447) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~