常量概念是为了使程序员能够在变和不变之间画一条界限。给C++程序设计项目中提供了安全性和可控性。——《C++编程思想》
在编程中要尽可能多的使用const,这样可以获得编译器的帮助,以便写出健壮性的代码。
define宏定义,可以将常量赋值给一个变量,但由于在编译过程中只是简单的进行文本替换,并不会对赋值语句进行检查,因此会存在很多潜在的威胁,一旦定义出错,整个调用过程也讲出错。所以C++创始人为了避免这种错误才提出了用const来代替,同时会对所定义的常量进行语法检查。 并且defne是不会给名字分配内存空间的,仅仅是一个常数的别名而已(字面常量存储在常量存储区或立即数形式出现),但是const变量会分配自己的内存空间,具有自己的地址。从这以后可以被用于指针、函数变量、返回类型、类对象和成员函数,用法有所区别,但是概念是一致的。
#define PI 3.1415926 //一般出现在头文件中,不是严格的语句不加“;”
const length = 10;//若不加类型名就默认是int类型,等同于 const int length = 10;
一、const常量
使用形式: const 类型 变量名 = 常量值;
定义常量时需要同时进行初始化!例如:const int a = 10; const int arr[3] = {0,1,2};只有一种情况是不需要初始化的,那就是声明为外部变量。
const定义的变量并不是存储在常量存储区域。const类型的存储跟一般的变量没有区别,在外部定义的存储在全局数据区,static的存储在静态数据区,在函数内部定义的存储在栈,const跟非const存储上没区别。
事实上,const在C和C++中是不同的!
//C
int main()
{
const int n = 5;
int arr[n];
return 0;
}
---------------------------
output:
1>------ 已启动全部重新生成: 项目: Project1, 配置: Debug Win32 ------
1> main.c
1>e:\cpp\cppprimer\project1\main.c(5): error C2057: 应输入常量表达式
1>e:\cpp\cppprimer\project1\main.c(5): error C2466: 不能分配常量大小为 0 的数组
1>e:\cpp\cppprimer\project1\main.c(5): error C2133: “arr”: 未知的大小
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========
在C语言中用常量n去初始化数组arr会发现出现错误。
主要原因是:
1.这个问题讨论的是“常量”与“只读变量”的区别。常量肯定是只读的,例如数字5, 字符串“abc”等。而“只读变量”则是在内存中开辟一个地方来存放它的值,只不 过这个值由编译器限定不允许被修改。C语言关键字const就是用来限定一个变量不允许被改变的修饰符。上述代码中变量n被修饰为只读变量,可惜再怎么修饰也不是常量。而ANSI C规定数组定义时维度必须是“常量”,“只读变量”也是不可以的。
2.在ANSI C中,这种写法是错误的,因为数组的大小应该是个常量,而const int n,n只是一个变量(常量 != 不可变的变量,但在标准C++中,这样定义的是一个常量,这种写法是对的),实际上,根据编译过程及内存分配来看,这种用法本来就应该是合理的,只是 ANSI C对数组的规定限制了它。那么在c语言中我们如果想定义一个事实常量该怎么定义呢?在C语言中我们定义常量的方法可以通过#define宏定义或者enum,这两个是C语言中常用的定义常量的方法。这样上述问题就可以解决了。
用这样的方法在C++中定义是没有问题的。
//C++
int main()
{
const int n = 5;
int arr[n];
return 0;
}
1>------ 已启动全部重新生成: 项目: 测试, 配置: Debug x64 ------
1> main.cpp
1>e:\cpp\测试\测试\main.cpp(20): warning C4101: “arr”: 未引用的局部变量
1> 测试.vcxproj -> E:\CPP\测试\x64\Debug\测试.exe
1> 测试.vcxproj -> E:\CPP\测试\x64\Debug\测试.pdb (Full PDB)
========== 全部重新生成: 成功 1 个,失败 0 个,跳过 0 个 =