C++笔记(二)~const | constexpr | 类型别名 |auto
【摘要】 const指针定义:指针是一个常量,初始化后,指针(存放这个指针的地址值)就不可以改变了。示例代码#include<iostream>using namespace std;int main(){ int i=1; // 这句话可以看出在 int *p=&i 上面又加了一层含义:这个指针是常量 初始化后就不可以改变了 int *const p=&i; cout...
const指针
定义:指针是一个常量,初始化后,指针(存放这个指针的地址值)就不可以改变了。
示例代码
#include<iostream>
using namespace std;
int main(){
int i=1;
// 这句话可以看出在 int *p=&i 上面又加了一层含义:这个指针是常量 初始化后就不可以改变了
int *const p=&i;
cout<<"i="<<i<<endl;
// 用法还是和原来*p一样 只是常量化 不可以更改了
cout<<"*p="<<*p<<endl;
return 0;
}
运行结果
顶层const与底层const
- 顶层const:指针本身是常量。更一般的说,顶层const可以表示任意的对象是常量
- 底层const:指针指向的对象是一个常量
解释:指针自身就是一个对象,同时也可以指向其他对象。区分顶层const与底层const就是依据:指针自身是否是常量。若是常量,则是顶层const;反之,则是底层const。对于顶层const,要求可以放宽,不一定必须要求指针是常量,因为指针也是对象,所以顶层const更加一般的定义就是:对象是常量。
示例代码
#include<iostream>
using namespace std;
int main(){
int i=0;
int *const p1=&i;//顶层const
const int ci=42;//顶层const 属于其一般定义:顶层const可以表示任意的对象是常量
const int *p2=&ci;//底层const,因为ci定义为:const int ci
const int *const p3=p2;//左边const是底层const 右边const是顶层const
return 0;
}
// 代码解释
// int *const p1 是在int *p1 上面的变形,强调此时的指针是常量
// const int ci=42 是在 int ci=42 上面的变形,强调此时的ci是int类型,且为常量
// const int *p2=&ci 解释:因为ci就是const(常量),所以其指针也必须是对应的常量
// 假设是 int ci=42 那么对应指针为:int *p2=&ci
// 而此时ci确实 const int 所以对应的指针也应该在最前面加上const: const int *p2=&ci
// const int *const p3=p2 是在 const int *p3的变形
// 因为指针p2的定义就是 const int *p2
// 如果此时我需要用另一个指针来替代p2
// 所以定义为 const int *p3=p2 (对应原则)
// 这时候p3指针和p2指向同一个对象ci,如果我们又希望p3是一个常量指针
// 所以定义为:const int *const p3=p2
// *const意思就是:这个指针是const常量
常量表达式
定义:值不会改变且在编译过程就能得到计算结果的表达式
示例代码
const int max=1;//是常量表达式
const int p=max+1;//是常量表达式
const int q=get()//不是常量表达式 需要运行get()函数后才可以得到值
constexpr
定义:是一种类型,便于编译器验证变量值是否为常量表达式。一般来说,如果认为一个变量是常量表达式,那么就可以把它声明为constexpr类型。
示例代码
constexpr int max=1;
constexpr int p=max+1;
constexpr int se=size();// 这里需要确定size同样也是一个constexpr类型的函数才是正确的
注意:如果constexpr声明中定义了一个指针,那么限定符constexpr仅对指针有效,与指针所值的对象无关
示例代码
#include<iostream>
using namespace std;
#define constexpr const
int main(){
const int *p=nullptr;//p是一个指向int型常量的指针 底层const
constexpr int *q=nullptr;//q是一个指向int型的常量指针 顶层const
return 0;
}
类型别名
定义:某种类型的别名,比如int类型,我们可以用x作为它的别名,在有x的地方就相对于int类型。
定义类型别名的两种方法
- 使用关键字typedef
- 使用别名声明 using
方法一:使用关键字typedef
typedef int x;//x是int的同义词
typedef x base,*p;// base是x的同义词,也就是int的同义词 p是int* 的同义词
测试代码
#include<iostream>
using namespace std;
int main(){
typedef int x;
typedef x y,*p;
int a=0;
x b=1;// 相当于 int b=1
y c=2;// 相当于 int c=2
int *q=&a;// 和int* q=&a 意思一样
p q2=&a;// 同 int *q2=&a
cout<<"a="<<a<<endl;// a=0
cout<<"b="<<b<<endl;// b=1
cout<<"c="<<c<<endl;// c=2
cout<<"*q="<<*q<<endl;// *q=0
cout<<"*q2="<<*q2<<endl;// *q2=0
return 0;
}
测试结果
方法二:使用别名声明 using
using x=int // 写法与typedef有区别
测试代码
#include<iostream>
using namespace std;
int main(){
using x=int;
using y=x;
// using *p=x; 这里不知道应该怎么写 达到和上一个示例typedef一样的效果
int a=0;
x b=1;// 相当于 int b=1
y c=2;// 相当于 int c=2
cout<<"a="<<a<<endl;// a=0
cout<<"b="<<b<<endl;// b=1
cout<<"c="<<c<<endl;// c=2
return 0;
}
测试结果
auto
编译器自动去分析一个对象是啥类型。
注意点:
- 一般会忽略顶层const,保留底层const
- 如果需要auto类型是顶层const,则需要明确指出
- 当设置一个类型为auto的引用时 初始值中的顶层常量属性仍然保留
示例代码
#include<iostream>
using namespace std;
int main(){
int i=0;
int &r=i;//r是i的别名
auto a=r;// a是一个int类型 (r只是i的别名,i是int类型)
const int ci=i,&cr=ci;
auto b=ci;// b是一个int类型整数(auto一般会忽略顶层const)
auto c=cr;// c是一个int类型的整数(cr只是ci的别名,该句代码意思同上)
auto d=&i;// d是一个int类型的指针
auto e=&ci;// e是一个指向int类型常量的指针 对常量对象取地址是底层const
const auto f=ci;// f是一个int类型常量 若不要忽略顶层const 则手动加上const
// 设置一个类型为auto的引用时 初始值中的顶层常量属性仍然保留
auto &g=ci;// 整型常量的引用
// 易错:
auto t=0;//正确
//auto &h=42; //错误:不可以为非常量引用绑定字面值
const auto &j=42;//正确:可以为常量引用绑定字面值
return 0;
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)