const使用小结

const VS enum和#define

在C++中,常量有3种表达方式:cosnt, enum和#define,这3种方式有什么不同呢?
1. #define在编译预处理时进行数据替换,没有存储空间;
   enum是编译时常量,没有存储空间;
   const将会分配数据存储空间(取决于编译器是否进行constant propagation)。
2. #define在debug调试时看不到变量名;
   enum在调试时可以看见变量名,但不能获取没有地址;
   const在调试时可以看见变量名和地址(所以只有const能获取变量地址、传地址)。
3. enum和const是类型安全的,而#define不是;
   只有enum和#define可以被用于 switch。


一些概念

1. const的作用域是整个文件,默认为内部连接。为了使const成为外部连接以便让另外一个文件可以对它引用,必须明确把它定义成extern。extern const强制进行了空间分配,extern意味着使用外部链接,因此必须分配存储空间。
2. const是运行期常量,加上static const后变为编译器常量。


常量折叠

先看例子:

#include <iostream>
using namespace std;
int main()
{
    const int a = 2*5; 
    int *b = (int*)&a;
    *b = 20;
    cout << "&a = " << &a << ',' << "b = " << b <<endl
	    << "a = " << a << ',' << "*b = " << *b <<endl;
    return 0;
}
输出结果为:

&a = 0x7fffc239893c,b = 0x7fffc239893c
a = 10,*b = 20
这时会发现&a和b的值(地址)一样,而a和*b的值不一样,就是说在相同的地址下的内存空间有不同的值。  
为什么呢?  
因为在编译期间进行了优化,即常量折叠(const folding),程序在编译过程中经过两种过程:1.const folding; 2.copy propagation。
const folding:上例中const int a = 2*5;  计算表达式的值时,编译器将2 * 5算成10,这个过程被称为const folding;
copy propagation:编译器在遇到a这个标识符时,自动将a替换成10,而不是去相应地址中取值,这个过程就是copy propagation.
上例就是这两个过程的结果,以后代码中遇到a的地方,编译器就自动将a替换成10.    
常量折叠概念:常量折叠是在编译时间简单化常量表达的一个过程。简单来说就是将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。  


编译时常量转运行时

编译时常量在编译后变量值已经确定,程序运行时常量值保持不变,例如:const int RUN_TIME = 1;
而运行时常量在程序运行时每次值都不一样。
例如:

int read_at_runtime()
{ 
  int val; 
  std::cin >> val; 
  return val; 
}
const int RUN_TIME = read_at_runtime();

以下下几种情况不能使用编译时常量转运行时:
1. 数组边界; 2.switch case表达式; 3.位域长; 4.枚举初始化; 5.模板的非类型参数赋值。


你可能感兴趣的:(const使用小结)