C++ const使用

const使用

C++ 中的 const 使用需要注意,const 对象必须初始化并且默认情况下,cosnt 对象只在文件内有效。

const对象必须初始化

  • 因为 const 对象一旦创建,就不能改变了。

cosnt对象只在文件内有效

  • const 对象默认作用域为:文件作用域。
  • 普通变量默认作用域:整个程序。
  • 对于一般的对象 如 int a=9;;我们知道它的作用域是整个程序的,在 1.cpp 和 2.cpp 中包含同一个定义了 int a=9;的头文件,因为 int a=9;作用域是整个程序,所以会产生错误。

那为什么 const int a=9;不会产生错误呢。原因就是 const int a=9;的默认作用范围是文件作用域的。即,尽管在 1.cpp 和 2.cpp 中包含同一个定义了 const int a=9;的头文件,但由于 const int a=9;是文件作用域的,包含了头文件的 1.cpp 和 2.cpp 尽管都包含了 const int a=9;但他们是各自文件内的 const 对象,两者互不相干,就像不同函数中定义了相同的变量名一样。

所以,通过在头文件中定义 const 对象,可以实现多个文件使用相同的常量值,这在实际的程序中很常见。那么如何使用其他文件中的 const?

说到这里,有一点疑问需要解决:如果想在别的文件中访问本文件中的 const 对象该怎么办,如果都是单是在别的文件中使用 extern const int a = 9; 的话,不会起任何作用,因为已经提示 const int a = 9;是文件作用域的。

所以应该在需要被其他文件使用的 const 对象定义成这样:extern const int a = 9; 而在别的需要使用这个 const 对象的地方声明:extern const int a; 前者是定义,后者是声明。这样就可以使用了。

常量折叠

int main() { int i0 = 11; const int i=0; //定义常量i int *j = (int *) &i; //看到这里能对i进行取值,判断i必然后自己的内存空间                 //请注意,int *j = &i;是不对的哦,我们在第4节讲过~ *j=1; //对j指向的内存进行修改 printf("%d\n%d\n%d\n%d\n",&i,j,i,*j); //观看实验效果 const int ck = 9; //这个对照实验是为了观察,对常量ck的引用时,会产生的效果 int ik = ck; int i1 = 5; //这个对照实验是为了区别,对常量和变量的引用有什么区别 int i2 = i1; return 0; }

上面的代码会输出:

0012ff7c 0012ff7c 0 1

这能说明什么,至少能说明两点:

  1. i 和 j 地址相同,指向同一块空间,i 虽然是可折叠常量,但是,i 确实有自己的空间。

  2. i 和 j 指向同一块内存,但是 *j = 1 对内存进行修改后,按道理来说,*j==1, i 也应该等于 1,而实验结果确实 i 实实在在的等于 0,这是为什么呢,就是本文所说的内容,i 是可折叠常量,在编译阶段对i的引用已经别替换为 i 的值了,也就是说:

    printf("%d\n%d\n%d\n%d\n",&i,j,i,*j)

    中的 i 已经被替换,其实已经被改为:

    printf("%d\n%d\n%d\n%d\n",&i,j,0,*j)

const修饰函数

const 放在函数后表示这个函数是常成员函数, 常成员函数是不能改变成员变量值的函数。const 限定符,它把一个对象转换成一个常量。

  1. 非常量成员函数不能被常量成员对象调用,因为它可能企图修改常量的数据成员。
  2. 非常量成员函数不能被常量实例调用,因为它可能企图修改常量的数据成员。

const成员变量

#include <iostream> using namespace std; class A { public: A(int size) : SIZE(size) {}; private: const int SIZE; }; int main() { A a(100); }

在类中声明变量为 const 类型,但是不可以初始化。const 常量的初始化必须在构造函数初始化列表中初始化,而不可以在构造函数函数体内初始化。

此时的 const 变量属于具体的一个对象,如何在整个类中都恒定不变呢?答案是利用枚举,举例:

#include <iostream> using namespace std; class A { private: enum {SIZE = 100}; public: int array[SIZE]; }; int main() { A a; }

枚举常量不会占据对象的存储空间,在编译时被全部求值。但是,它隐含的数据对象类型为整形,不能表示其他类型。