#define是ISO C/C++预处理器接受的预处理命令,是标准的语言特性。
const 也是ISO C/C++的语言特性,但是在C/C++中有些区别。
严格来说,#define定义符号常量和const定义常量对象各有使用范围,不存在哪个优于哪个的问题。不过仅就C++单一源文件内定义字面量作为符号常量而言,const的主要优点是:
#define是符号替换,只要定义符合预处理命令的语法,预处理器就不会报错,只保证被替换处“字面上地”符合定义的替换规则——常量检查由编译器在之后的语法检查中检查对字面量的操作时进行(字面量的值总是编译期常量,因此可以对修改操作报错);而在编译器进行语法检查(静态类型检查)时会把任何可能的直接修改const对象操作作为编译错误——这点可以预防一些误用,如LS所说,如果用#define a 1+2而不是#define a (1+2) 的话,在表达式中a就很可能不是所要的值。
当然,间接通过显式类型转换指向const对象的指针类型然后用*操作符去修改的话,还是可以骗过编译器的(不报错),不过这本身就是逻辑上的错误,因此不能保证程序的行为一定符合预期。不作为常量的对象不应该使用const修饰。
另外,const有可能不是真正意义上的(编译期)常量,例如在多个翻译单元使用extern修饰的同一个const对象,或者非基本类型的const对象。此时const修饰的对象只是一个禁止修改(由编译器静态类型检查保证)的变量而已,如果没有被优化掉,一般占用更多的目标文件大小,运行期效率比#define替换得到的字面量(可能被编译为立即数)低。由于不是编译期确定的常量,这样的const对象即使是整数类型也不能作为case的标号,而直接#define整数字面量就可以。
PS.在C语言中,const对象总不是编译期确定的常量。
====
[原创回答团]
参考资料:原创