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指向的对象都不可变。
修饰函数参数
修饰函数的返回值