六一的部落格


关关难过关关过,前路漫漫亦灿灿。




说明

类型修饰符

采用《C++ Primer》中的概念, 和常量指针,指针常量,常量引用这些概念相冲突

不使用以下定义:

-
常量指针 pointer to const 指向常量的指针
指针常量 const pointer 指针是常量
常量引用 const reference 引用常量

使用以下定义:

-
具有顶层const的指针 const pointer const指针
具有底层const的指针 pointer to const
具有底层const的左值引用 reference to const const引用

不涉及迭代器


顶层const

  1. 描述对象自身的读写权限

    只有对象能拥有顶层const属性:

    • 引用是变量不是对象,不能拥有顶层const
    • 指针是对象, 可以拥有顶层const
  2. 拥有顶层const的对象只读,必须显式初始化

1const T var = val;

具有顶层const的指针

const指针

具有顶层const属性的指针

  • 不可指向其他对象: 不能对具有顶层const的指针指向写操作,即不能使其指向其他对象
  • 指向对象的读写权限不受影响
1T var, * const cp = &var;

底层const

指针和引用可间接访问对象

  1. 描述间接访问对象读写权限的开放情况

    基于间接访问,只有引用和指针可以拥有底层const属性

  2. 如果指针和引用拥有底层const,通过二者间接访问对象时, 无法执行写操作

    间接访问对象不一定具有顶层const,但对指针和引用锁定写权限

  3. 如果指针不具有顶层const属性, 可以修改指针指向


指针之间的赋值过程中, 底层const属性被传递,要求左右两侧运算对象的底层const一致


初始化引用和指针时,如果间接访问对象具有顶层const,要求引用和指针具有底层const

1int a = 5, *p = &a;
2const int * const cpc = p; // cpc具有顶层const和底层const
3const int b = 6;
4const int *pc = &b;        // pc必须有底层const
5
6int *p2 = pc;              // 错误:p2必须有底层const
7int &ri = b;               // 错误:ri必须有底层const

具有底层const的指针

1const T *pc;

具有底层const的左值引用

const引用

1int i = 5;
2const int &rci = i;                // 绑定对象锁定写权限
3i = 6;
4cout << rci<< endl;                // 6
5cout << &rci<< endl << &i << endl; // 二者地址相同

可以用来绑定一个右值表达式

被绑定对象对具有底层const的左值引用锁定写权限

发生隐式转换时, 表达式为纯右值表达式, 纯右值表达式物质化得到速亡值表达式, 为一个即将销毁且无其他使用者的对象; 将引用绑定到该对象

初始值为表达式,或存在隐式类型转换,是纯右值表达式

纯右值表达式物质化得到速亡值表达式,对应一个明确对象,将引用绑定到该对象

 1double dval = 3.14;
 2const int &rci = dval;                   // 变量表达式是一个左值, 将其用来初始化rci时, 发生一次隐式转换, rci实际绑定的是隐式转换的结果
 3
 4//   <=>
 5// const int temp = dval;
 6// const int &rci = temp;
 7
 8cout << &dval << endl << &rci << endl;   // 二者地址不同
 9cout << rci << endl;                     // 3
10
11
12const double &rcd = dval;                // 使用rcd绑定dval
13cout << &dval << endl << &rcd << endl;   // 二者地址相同

具有底层const的右值引用

间接访问对象对具有底层const的右值引用锁定写权限

 1#include <iostream>
 2int fcn(int a) { return a + 1; }
 3int main()
 4{
 5    int a = 5;
 6    const int &&r = fcn(a);
 7    r = 20;  // 错误: 无法通过r读写绑定对象
 8
 9    int &&r2 = fcn(5);
10    r2 = 10; // 正确
11    return 0;
12}

定义同时具有顶层const和底层const的指针

具有底层const的const指针

1const int *p; // 具有底层const的指针
2
3int a;
4int *const cp = &a; // 具有顶层const的指针, 即const指针
5
6const int * const cpc = a; // 同时具有顶层const和底层const的指针

总结

  1. 所有对象都可以拥有顶层const,但只有支持间接访问的指针和引用可以拥有底层const
  2. 指针既可以拥有顶层const, 也可以拥有底层const
  3. 引用只能拥有底层const

const属性和作用域

  1. 在函数外声明的顶层const对象,具有文件作用域
  2. 在函数外声明的底层const对象,具有全局作用域

创建具有全局作用域的顶层const对象

声明或定义顶层const对象时,使用extern关键字,使之具有全局作用域

包含显式初始化的声明即定义,只能在一处定义


具有文件作用域的顶层const对象和具有全局作用域的顶层const对象,因为作用域不同,可以出现在同一个文件中


file实现

  1. 头文件
    1void print();
  2. 定义
     1#include <iostream>
     2using std::cout;
     3using std::endl;
     4
     5const int ci = 70;        // 文件作用域
     6extern const int ci;      // 全局作用域
     7
     8void print()
     9{
    10    cout << "In print:\n";
    11    cout << "ci = " << ci << endl;
    12}

main函数测试

 1#include <iostream>
 2#include "file.h"
 3
 4using std::cout;
 5using std::endl;
 6
 7extern const int ci = 7;           // 顶层const:全局作用域
 8
 9int main()
10{
11    cout << "In main:\n";
12    cout << "ci = " << ci << endl;
13
14    print();
15    return 0;
16}
  1. 编译

    1g++ -std=c++11 file.cpp main.cpp
  2. 运行结果

    In main:
    ci = 7
    In print:
    ci = 70

const限定符



说明

类型修饰符

采用《C++ Primer》中的概念, 和常量指针,指针常量,常量引用这些概念相冲突

不使用以下定义:

-
常量指针 pointer to const 指向常量的指针
指针常量 const pointer 指针是常量
常量引用 const reference 引用常量

使用以下定义:

-
具有顶层const的指针 const pointer const指针
具有底层const的指针 pointer to const
具有底层const的左值引用 reference to const const引用

不涉及迭代器


顶层const

  1. 描述对象自身的读写权限

    只有对象能拥有顶层const属性:

    • 引用是变量不是对象,不能拥有顶层const
    • 指针是对象, 可以拥有顶层const
  2. 拥有顶层const的对象只读,必须显式初始化

1const T var = val;

具有顶层const的指针

const指针

具有顶层const属性的指针

  • 不可指向其他对象: 不能对具有顶层const的指针指向写操作,即不能使其指向其他对象
  • 指向对象的读写权限不受影响
1T var, * const cp = &var;

底层const

指针和引用可间接访问对象

  1. 描述间接访问对象读写权限的开放情况

    基于间接访问,只有引用和指针可以拥有底层const属性

  2. 如果指针和引用拥有底层const,通过二者间接访问对象时, 无法执行写操作

    间接访问对象不一定具有顶层const,但对指针和引用锁定写权限

  3. 如果指针不具有顶层const属性, 可以修改指针指向


指针之间的赋值过程中, 底层const属性被传递,要求左右两侧运算对象的底层const一致


初始化引用和指针时,如果间接访问对象具有顶层const,要求引用和指针具有底层const

1int a = 5, *p = &a;
2const int * const cpc = p; // cpc具有顶层const和底层const
3const int b = 6;
4const int *pc = &b;        // pc必须有底层const
5
6int *p2 = pc;              // 错误:p2必须有底层const
7int &ri = b;               // 错误:ri必须有底层const

具有底层const的指针

1const T *pc;

具有底层const的左值引用

const引用

1int i = 5;
2const int &rci = i;                // 绑定对象锁定写权限
3i = 6;
4cout << rci<< endl;                // 6
5cout << &rci<< endl << &i << endl; // 二者地址相同

可以用来绑定一个右值表达式

被绑定对象对具有底层const的左值引用锁定写权限

发生隐式转换时, 表达式为纯右值表达式, 纯右值表达式物质化得到速亡值表达式, 为一个即将销毁且无其他使用者的对象; 将引用绑定到该对象

初始值为表达式,或存在隐式类型转换,是纯右值表达式

纯右值表达式物质化得到速亡值表达式,对应一个明确对象,将引用绑定到该对象

 1double dval = 3.14;
 2const int &rci = dval;                   // 变量表达式是一个左值, 将其用来初始化rci时, 发生一次隐式转换, rci实际绑定的是隐式转换的结果
 3
 4//   <=>
 5// const int temp = dval;
 6// const int &rci = temp;
 7
 8cout << &dval << endl << &rci << endl;   // 二者地址不同
 9cout << rci << endl;                     // 3
10
11
12const double &rcd = dval;                // 使用rcd绑定dval
13cout << &dval << endl << &rcd << endl;   // 二者地址相同

具有底层const的右值引用

间接访问对象对具有底层const的右值引用锁定写权限

 1#include <iostream>
 2int fcn(int a) { return a + 1; }
 3int main()
 4{
 5    int a = 5;
 6    const int &&r = fcn(a);
 7    r = 20;  // 错误: 无法通过r读写绑定对象
 8
 9    int &&r2 = fcn(5);
10    r2 = 10; // 正确
11    return 0;
12}

定义同时具有顶层const和底层const的指针

具有底层const的const指针

1const int *p; // 具有底层const的指针
2
3int a;
4int *const cp = &a; // 具有顶层const的指针, 即const指针
5
6const int * const cpc = a; // 同时具有顶层const和底层const的指针

总结

  1. 所有对象都可以拥有顶层const,但只有支持间接访问的指针和引用可以拥有底层const
  2. 指针既可以拥有顶层const, 也可以拥有底层const
  3. 引用只能拥有底层const

const属性和作用域

  1. 在函数外声明的顶层const对象,具有文件作用域
  2. 在函数外声明的底层const对象,具有全局作用域

创建具有全局作用域的顶层const对象

声明或定义顶层const对象时,使用extern关键字,使之具有全局作用域

包含显式初始化的声明即定义,只能在一处定义


具有文件作用域的顶层const对象和具有全局作用域的顶层const对象,因为作用域不同,可以出现在同一个文件中


file实现

  1. 头文件
    1void print();
  2. 定义
     1#include <iostream>
     2using std::cout;
     3using std::endl;
     4
     5const int ci = 70;        // 文件作用域
     6extern const int ci;      // 全局作用域
     7
     8void print()
     9{
    10    cout << "In print:\n";
    11    cout << "ci = " << ci << endl;
    12}

main函数测试

 1#include <iostream>
 2#include "file.h"
 3
 4using std::cout;
 5using std::endl;
 6
 7extern const int ci = 7;           // 顶层const:全局作用域
 8
 9int main()
10{
11    cout << "In main:\n";
12    cout << "ci = " << ci << endl;
13
14    print();
15    return 0;
16}
  1. 编译

    1g++ -std=c++11 file.cpp main.cpp
  2. 运行结果

    In main:
    ci = 7
    In print:
    ci = 70