C++之const限定符

时间:2022-01-17 15:05:44

        C++程序设计中,const限定符和很多方面都有关系,比如说引用、数组、指针、函数等等,这里对const限定符的使用做下小结。

1. 定义const对象

        const限定符将一个对象转换成一个常量,定义后就不能修改,因此必须在定义时进行初始化         const int bufSize = 512;

2. const对象默认为文件的局部变量

        在全局作用域声明的const变量是定义该对象文件的局部变量。此变量只存在于那个文件中,不能被其他文件访问。通过指定const变量为extern,就可以在整个程序中访问const对象:         // file_1.cc         // defines and initializes a const that is accessible to other files         extern const int bufSize = fcn();         // file_2.cc         extern const int bufSize;  // uses bufSize from file_1         for (int index = 0; index != bufSize; ++index)          //...

3. const引用

        const引用是指向const对象的引用:         const int ival = 1024;         const int &refVal = ival;  // ok: both reference and object are const         int &ref2 = ival;                // error: nonconst reference to a const object         const引用可以初始化不同类型的对象或者初始化为右值,如字符值常量:         int i = 42;         // legal for const reference only         const int &r = 42;         const int &r2 = r + i;         同样的初始化对非const引用却是不合法的。也就是说,非const引用只能绑定到与该引用同类型的对象,const引用则可以绑定到不同但相关的类型的对象或绑定到右值

4. 指针和const限定符

4.1 指向const对象的指针

        如果指针指向const对象,则不允许用指针来改变其所指的const值。为了保证这个特性,C++语言强制要求指向const对象的指针也必须具有const特性:         const double *cptr;  // cptr may point to a double that is const         这里的cptr是一个指向double类型const对象的指针,const限定了cptr指针所指向的对象类型,而并非cptr本身。也就是说,cptr本身并不是const,在定义时不需要对其进行初始化。如果需要的话,允许cptr重新赋值,使其指向另一个const对象。把一个const对象的地址赋给一个普通的、非const对象的指针也会导致编译错误,但允许把非const对象的地址赋给指向const对象的指针,该指针指向的值不能被修改         const double pi = 3.14;         double *ptr = π       // error: ptr is a plain pointer         const double *cptr = & pi; // ok; cptr is a pointer to const

4.2 const指针

        const指针表示指针是const,指针的值不能修改,这就意味着不能使其指向其他对象,也必须在定义时初始化         int errNumb = 0;         int *const curErr = &errNumb;         指针本身是const并没有说明是否能修改指针所指向的对象的值,指针所指向的对象的值能够被修改完全取决于该对象的类型。如果curErr指向一个普通的非常量int型对象ErrNumb,则可使用curErr修改该对象的值。

4.3 指向const对象的const指针

        const double pi = 3.14159;         // pi_ptr is const and points to a const object        const double *const pi_ptr = π        本例中,既不能修改pi_ptr所指向对象的值,也不允许修改该指针的指向。

5. const对象与数组初始化

        数组在定义时,其维数必须用值大于等于1的常量表达式定义。此常量表达式只能包含整型字面值常量、枚举常量或者用常量表达式初始化的整型const对象。非const变量以及要到运行阶段才能知道其值的const变量都不能用于定义数组的维数。         const unsigned buf_size = 512;         char input_buffer[buf_size];  // ok: const variable         const unsigned sz = get_size();         int valz[sz];  // error: size not known until run time

6. const形参

6.1 非引用形参

        在调用函数时,如果该函数使用非引用的非const形参,则既可给该函数传递const实参,也可传递非const实参。         如果将形参定义为非引用的const类型:         void fcn(const int i) {/* fcn can read but not write to i */}         则在函数中,不可以改变形参的值。由于实参仍然是以副本的形式传递,也就是说实参的值不受函数调用的影响,因此传递给fcn的既可以是const对象也可以是非const对象。

6.2 引用形参

        在向函数传递大型对象时,需要使用引用形参,因为复制实参对于大部分的类类型或者大型数组,效率太低。编写一个比较两个string对象长度的函数作为例子。这个函数需要访问每个string对象的size,但不必修改这些对象。由于string对象可能相当长,所以我们希望避免复制操作。使用const引用就可避免复制:         //compare the length of two strings         bool isShorter(const string &s1, const string &s2)         {             return s1.size() < s2.size();         }         如果函数具有普通的非const引用形参,则显然不能通过const对象进行调用。非const引用形参只能与完全同类型的非const对象关联