变量和基本类型
浮点数用double
,整数一般int
,超过范围用long long
,知道没负数用unsigned
。
变量使用extern
进行声明,声明不是定义,使用该关键字后,不要进行显式初始化操作,变量可以声明多次,但是只能定义一次。
引用:
int r2=10;
int &r1=r2;
r1
和r2
是同一个数据,只是名称不同。
void*
指针可以存放任意对象的地址。
int* p, p1; // p是int*类型,而p1是int类型,这样写容易误解
int *p2, p3; // 这是规范写法
const
限定符仅仅在文件的内部有效,且必须进行初始化,否则无意义,编译时会找到变量名进行替换,类似于#define
的作用。如果要在多个文件中使用同一个const
变量,前面必须使用extern
进行说明
const
可以进行引用,但是对常量的引用不能修改它绑定的对象
const int ci=1024;
const int &r1=ci; // 正确
r1=ci; // 错误,r1是对常量的引用
int &r2=ci; // 错误,非常量不能引用常量
int i=10;
// 正确,但是不允许通过r2修改i的值,始终和i的值一致,r2不可以绑定其他变量
const int &r2=i;
const
可以用于指针:
double d=10;
const double *p=d; // 不能通过p修改d的值,但是可以改变p的指向
double *const p1=d; // p1始终指向d
const double *const p2=d; // p2始终指向d,而且不能用p2修改d的值
顶层const
表示指针本身是个常量;底层const
表示指针所指的对象是个常量,但本身的指向可以变。更一般的,顶层const
表示任意对象是常量。
int i=0;
int *const p1=&i; // 顶层const,p1只能指向i
const int ci=i; // 顶层const,ci的值不能变
const int *p2=i; // 底层const,p2的值可以变
const int *const p3=p2; // 右侧是顶层const,左侧是底层const
const int &r=ci; // 用于声明引用的都是底层的const
顶层const
可以表示任意的对象是常量。进行拷贝时,对象对须有相同的底层const
资格!
常量表达式是值不会改变而且在编译过程就能得到计算结果的表达式。字面值是常量表达式,用常量表达式初始化的const
对象也是。
const int max_files=20; // 是
const int limit=max_files+1; // 是
int staff_size=11; // 不是
const int sz=get_size(); // 不是
constexpr
类型的变量,用于由编译器来验证变量的值是否是常量表达式,声明为该类型的变量一定是一个常量,且必须用常量表达式进行初始化。一般来说,如果变量是一个常量表达式,那么就声明为constexpr
类型。
constexpr int mf=20; // 20是常量表达式
constexpr int limit=mf+1; // mf+1是常量表达式
constexpr int sz=size(); // 只有size是constexpr函数时,才是正确的语句
字面值类型是编译期间就知道的,像算数类型、引用和指针等;而IO库,string
类型等则不是。用constexpr
声明的指针初始化必须是0、nullptr
或者存储于耨个固定地址中的对象。
类型别名:
// 两种别名的模式
typedef double dle;
using flt=float;
auto
自动类型推导,编译器自动进行类型的推断。使用auto
时,一条语句中的基本类型只能有一个。
auto i=0, *p=&i; // 正确,都是int的推导
auto sz=1, pi=3.14; // 错误,出现了int和double
auto
对引用变量进行推导时,实际参与初始化的是引用对象的值。
int i=0,&r=i;
auto a=r; // 实际上是i参与初始化
auto
推导时,忽略顶层的const
,保留底层的const
。
int i=0;
const int ci=i,&cr=ci;
auto b=ci; // b是整数,忽略顶层的const
auto c=cr; // c是整数,忽略顶层的const
auto d=&i; // d是整型指针
auto e=&ci; // 指向整数常量的指针
如果需要顶层常量,需要自己标出:
const auto f=ci;
需要推导引用,也需要自己指出来:
auto &g=ci;
或者两者都用:
const auto &tmp=ci;
decltype
类型指示符,选择并返回操作数的类型。
decltype(f()) sum=x; // sum的类型就是f返回的类型
上述的例子中,编译器不实际调用函数f
,而是使用当发生f
调用时返回的类型作为sum
的实际值。decltype
处理顶层的const
和引用时,如果使用的表达式是一个变量,则返回变量的类型(包括顶层的const和引用在内):
const int ci=0,&cj=ci;
decltype(ci) x=0; // x的类型是const int
decltype(cj) y=x; // y的的类型是const int & 绑定到x上
decltype(cj) z; // 错误,引用必须初始化
表达式的内容是解引用,则decltype
会得到该类型的引用。
int i=42,*p=&i,&r=i;
decltype(r+0) b; // 加法的结果是int,因此b是未初始化的int
decltype(*p)c; // 错误,c是int& 必须初始化
decltype((variable))
(双层括号)的结果永远是引用,decltype(variable)
(一层括号)只有当variable
本身是一个引用时才是引用。