CONST关键字笔记

来源:互联网 发布:清除垃圾软件 编辑:程序博客网 时间:2024/06/17 11:58

const修饰的值并不是常量,而是只读的变量。其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。

C++ 里 const 变量一般默认 static 连接方式

也就是其它 .cpp 文件看不到,所以用 extern 声明也没用

可将 const 变量的声明放在 .h 文件里,需要使用此常量的 .cpp 都 #include 它
编译器通常不为普通const只读变量分配存储空间,而是将它们保存在符号表中,这使得Tam它成为一个编译期间的值,没有了存储和读内存的操作,使它的效率很高。

#define M 3        //宏常量

const int N = 5;  //此时未将N 放入内存

......

int i = N;  //此时为N 分配内存,之后不再分配

int I = M;  //预编译期间进行宏替换,分配内存

int j = N;  //没有内存分配

int J = M;   //再次进行宏替换,再次分配内存

const定义的只读变量从汇编角度上看,只是给出了对应的内存地址,而不是像 #define一样,给出的是立即数。所以,const定义的只读变量在程序运行过程中只有一份copy,因为他是全局的只读变量,放在静态区。#define 宏实在预编译阶段进行替换,const修饰的只读变量是在编译时确定其值。

?
下面的代码在存为C文件在VC6.0编译器下编译是错误的!为什么?
#include<stdio.h>
void main()
{
const int bufsize = 10 ;
char buf[bufsize] = {'a','b','c'};//error C2057:expected constant expression
//error C2466: cannot allocate an array of constant size 0
printf ("%S",buf);
}
在编译时,编译器并不知道const的值,它只是一个“运行时常量”。不是放在符号表里的。(编译原里的知识这里就不多讲了!)
然而把上面的代码改成CPP文件在VC6.0编译器下编译是通过的。
通常,C++编译器不为const创建存储空间,而是把它保存在“符号表”里,即“编译时常量”。默认情况下,C++中的const是内部连接的,也就是说,const仅在const被定义过
?
的文件里才是可见的。(因此,不用担心名字冲突)当定义一个const时,必须赋一个值给它,除非用extern做出了清楚的说明。当用extern说明了const时,编译器会强制为const
?
分配空间,而不是保存在符号表中。
 

const修饰的只读变量必须在定义的同时初始化。

用如下方法可以修改const常量,但是如果将const int i=0;放到main函数之外,作为全局变量,则施行的时候会报错。

#include<stdio.h>

main()
{
const int i=0;
int *p=&i;
*p=3;
printf("%d",i);
}

类中的常量:

在类中,const数据成员只在某个对象生存期内是常量,而对于整个类而言确实可变的,因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。

不能在类声明中初始化const数据成员,以下用法错误,因为类的对象还未被创建时,编译器不知道SIZE的值为多少:

class A

{
  const int SIZE = 100;

  int array[SIZE];

};

const数据成员的初始化只能在类构造函数的初始化中进行,例如:

class A

{

  A(int size);//构造函数

  const int SIZE;

};

A::A(int size):SIZE(size)

{

}

A a(100);//对象a的size值为100

A b(200);//对象b的size值为200

要建立在整个类中都恒定的常量,可用枚举常量来实现。但枚举常量是整数,不能表示浮点数

class A

{

  enum {SIZE1 = 100,SIZE2 = 200};

  int array1[SIZE1];

  int array2[SIZE2]; 


}

------------------

用const提高函数健壮性


1、const修饰函数参数

如果参数作输出用,不管是什么数据类型,也不管是采用指针传递还是引用传递,都不能加const,否则该参数将失去输出功能。

如果参数作为输入:

     值传递:形参变动不会影响实参,所以无需保护。不需要加const修饰。无需将void Func1(int x)写成void Func1(const int x),也无需将void Func2(A a)写成void Func2(const A a),A为用户自定义的数据类型。

  引用传递:对于非内部数据类型的参数而言,像void Func2(A a)这样声明的函数效率较低,因为函数体内将产生A类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都耗费时间。为了提高效率,可以将函数声明改为void Func2(A  &a),引用传递不产生临时对象。但可能改变参数a,所以可以改为void Func2(const A &a) ,但内部数据类型就不需要如此修改,因为int等类型不存在构造析构的过程,值传递和引用传递的效率相当。

  指针传递:加const修饰可以防止意外改动该指针。

void stringcopy(char * strdestination , const char strsource); //输出参数不可加const

用const修饰函数的返回值

  如果给“指针传递”方式的函数返回值加const修饰,那么函数返回值的内容不可以被修改,而且只能被赋给加const修饰的同类型指针:

const char *getstring(void);

char *str = getstring();//错误

const char *str = getstring();//正确


  如果函数返回采用“值传递”,由于函数会把返回值复制到外部临时存储单元,加const无作用:


不要把int getint(void)写成const int getint(void)


不要把A getA(void)写成const A getA (void)


-----------------------------------------------------


const修饰一般变量:


int const i = 2;或 const int i = 2;


修饰数组


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


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


修饰指针


const int *p;//p可变,p指向的对象不可变  常量指针


int const *p;//p可变,p指向的对象不可变 常量指针


int *const p;//p不可变,p指向的对象可变 指针常量


const int *const p;//指针p和p指向的对象都不可变。


修饰函数参数


修饰函数的返回值

原创粉丝点击