目录
易错知识点
const和指针的结合
const和一级指针的结合
正误转换
巧用技巧
const是否参与类型
const和二级指针的结合
正误转换
巧用技巧
温故知新
易错知识点
1、常量不能作为左值,防止直接修改常量的值
2、不能将常量的地址泄露给普通指针或普通引用变量,防止间接修改常量的值
// 关于易错知识点第2点
// 不能将常量的地址泄露给普通指针或普通引用变量,防止间接修改常量的值
const int a = 10;
const int * p = &a; // 正确写法!
// int * p = &a; // 错误写法!
// int * const p = &a; // 错误写法!
// 以下写法均正确!int a = 1;int * p1 = &a;const int * p2 = &a;int const * p3 = &a;int * const p4 = &a;const int * const p5 = &a;int const * const p6 = &a;
const和指针的结合
1、const修饰离它最近的类型
2、注意区分const修饰的类型和const修饰的表达式:
除去const和它修饰的类型,剩余部分就是const修饰的表达式(详见以下代码段)
3、如果const右边没有指针*,那么const不参与类型
const和一级指针的结合
正误转换
// 正确转换
// 1
const int * <= int *// 2
int * const * <= int * *
// const因它右边*而参与类型
// 因此可将int * const * <= int * *看做是const * <= *
// 所以是正确转换// 错误转换
// 1
int * <= const int *// 2
int * * <= int * const *
// const因它右边*而参与类型
// 因此可将int * * <= int * const *看做是* <= const *
// 所以是错误转换
巧用技巧
// const和一级指针的结合
// 巧用“除去const和它修饰的类型,剩余部分就是const修饰的表达式”技巧// 1
const int * p;
// const int * p;与int const * p;等价
// const修饰的类型为int,修饰的表达式为*p
// *p的值不能被修改,p的值可以被修改
// 指针p可以指向其它内存,但不能通过指针p修改内存的值// 2
int const * p;
// int const * p;与const int * p;等价
// const修饰的类型为int,修饰的表达式为*p
// *p的值不能被修改,p的值可以被修改
// 指针p可以指向其它内存,但不能通过指针p修改内存的值// 3
int * const p;
// *不能单独作为类型,const修饰的类型为int *,修饰的表达式为p
// p的值不能被修改,*p的值可以被修改
// 可以通过指针p修改内存的值,但指针p不能指向其它内存// 4
const int * const p;
// const int * const p;与int const * const p;等价
// const int * const p;相当于const int * p;和int * const p;的综合
// 前const修饰的类型为int,修饰的表达式为*p
// 后const修饰的类型为int *,修饰的表达式为p
// 不能通过指针p修改内存的值,指针p也不能指向其它内存// 5
int const * const p;
// int const * const p;与const int * const p;等价
// int const * const p;相当于int const * p;和int * const p;的综合
// 前const修饰的类型为int,修饰的表达式为*p
// 后const修饰的类型为int *,修饰的表达式为p
// 不能通过指针p修改内存的值,指针p也不能指向其它内存// 总结
// 第一类:const int * p;与int const * p;等价
// 第二类:int * const p;
// 第一类和第二类综合形成第三类:
// const int * const p;与int const * const p;等价
const是否参与类型
// const和一级指针的结合
// 关于“3、如果const右边没有指针*,那么const不参与类型”#include<iostream>
#include<typeinfo>
using namespace std;int main()
{int * p1 = nullptr;int * const p2 = nullptr;cout << "int * p1定义的p1的类型为" << typeid(p1).name() << endl;cout << "int * const p2定义的p2的类型为" << typeid(p2).name() << endl;cout << "总结:如果const右边没有指针*,那么const不参与类型" << endl;cout << "-------------------------------------------" << endl;const int * p3 = nullptr;cout << "const int * p3定义的p3的类型为" << typeid(p3).name() << endl;cout << "总结:如果const右边有指针*,那么const参与类型" << endl;return 0;
}
const和二级指针的结合
正误转换
// 错误转换
int * * <= const int * *
const int * * <= int * *
// 关于const int * * <= int * *是错误转换的说明// 例如,有如下错误代码:
int a = 1;
int * p = &a;
const int * * q = &p;
// 假如以上代码逻辑成立,
// 那么*q为指向const int类型的指针,那么可以写如下代码:
const int b = 2;
*q = &b;
// 值得注意的是,*q和p属于同一内存
// 而p是int *类型,是一个普通指针
// 这违背易错知识点第2点“不能将常量的地址泄露给普通指针或普通引用变量,防止间接修改常量的值”
// 所以const int * * <= int * *是错误转换
// 同理,int * * <= const int * *是错误转换
巧用技巧
// const和二级指针的结合
// 巧用“除去const和它修饰的类型,剩余部分就是const修饰的表达式”技巧// 1
const int * * q;
// const修饰的类型为int,修饰的表达式为**q
// q能被赋值
// *q能被赋值
// **q不能被赋值// 2
int * const * q;
// *不能单独作为类型,const修饰的类型为int *,修饰的表达式为*q
// q能被赋值
// *q不能被赋值
// **q能被赋值// 3
int * * const q;
// const修饰的类型为int * *,修饰的表达式为q
// q不能被赋值
// *q能被赋值
// **q能被赋值// 总结
// 第一类:const int * * q;
// 第二类:int * const * q;
// 第三类:int * * const q;
温故知新
1、注意理解前文的正确转换和错误转换!
2、如果const右边没有指针*,那么const不参与类型
// 1
int a = 1;
const int * p = &a;
// const int * <= int *,正确!
int * q = p;
// int * <= const int *,错误!// 2
int a = 1;
int * const p = &a;
// int * <= int *,正确!
int * q = p;
// int * <= int *,正确!// 3
int a = 1;
int * const p = &a;
// int * <= int *,正确!
int * const q = p;
// int * <= int *,正确!// 4
int a = 1;
int * const p = &a;
// int * <= int *,正确!
const int * q = p;
// const int * <= int *,正确!// 5(注意联系6和7)
int a = 1;
int * p = &a;
// int * <= int *,正确!
const int * * q = &p;
// const int * * <= int * *,错误!// 6(注意联系5和7)
int a = 1;
const int * p = &a;
// const int * <= int *,正确!
const int * * q = &p;
// const int * * <= const int * *,正确!// 7(注意联系5和6)
int a = 1;
int * p = &a;
// int * <= int *,正确!
const int * const * q = &p;
// const int * const * <= int * *,正确!// 8
int a = 1;
int * p = &a;
// int * <= int *,正确!
int * const * q = &p;
// int * const * <= int * *
// 相当于const * <= *,正确!// 9
int a = 1;
int * p = &a;
// int * <= int *,正确!
int * * const q = &p;
// int * * <= int * *,正确!// 10
int a = 1;
int * const p = &a;
// int * <= int *,正确!
int * * q = &p;
// 注意!注意!
// int * * <= int * const *
// 相当于* <= const *,错误!// 11
int a = 1;
const int * p = &a;
// const int * <= int *,正确!
int * const * q = &p;
// 注意!注意!
// int * const * <= const int * *
// 相当于const * <= *和int * <= const int *
// const * <= *,正确!
// int * <= const int *,错误!
// 综上,int * const * <= const int * *,错误!