4种变量初始化的方法
int val = 0;
int val = {0}; //C++11
int val{0}; //C++11
int val(0);
这种用花括号初始化的方法称作为”列表初始化 “, 这种初始化有一个重要特点:当进行有丢失信息风险的初始化行为时, 编译器将会报错.
long double ld = 3.1415926;
int a{ld},b={ld}; //列表初始化,有丢失信息信息风险时编译报错(error)
int c(ld),d=(ld); //正常执行,丢失信息(warning)
关于const与引用、指针
我们这样定义一个 引用
int val = 3; int &ref = val;
引用必须在定义时就指定其绑定的对象(初始化),一旦确定就不可再绑定别的对象,这一点上和const限定符的作用很相似.★
int &const ref = val; //其实就等价于 int &ref = val; //引用ref绑定val,且不可再绑定别的对象 //同时这是一种顶层const,下面我们将讨论什么是顶层、底层const
顶层、底层const
首先看几个例子
int val = 10;
const int *ptr = &val; //底层const,ptr可以更换所指对象
int const *ptr = &val; //等价于上面的写法
//这便是底层const,将ptr限定为指向一个常量(const <type_name>),禁止通过指针或引用来更改所指对象的值.
//而指针要指向谁(指针的值)是可以任意改变的.
//底层const对于引用,可以看做是一种天然自带的属性(见上面★句). 一起引用必须定义时就初始化,且不可再更改.
int *const ptr = &val; //顶层const,ptr不可以更换所指对象
//单仍然可以通过*ptr来修改所指对象(val)的值
const int *const ptr = &val; //同时有底层和顶层const
弄清楚const的层次关系,以及const究竟对谁起作用 是非常重要的.
一个有效的方法是从右向左阅读:
1.在最后一个例子中,离ptr最近的是const(而不是*),这说明ptr本身是一个常量对象,它的值不可以改变(不能更换所指目标).
2.继续向左阅读,下一个遇到的是*符号,这说明ptr是一个指针(不论类型和其他限定条件,它起码是一个指针).
3.接着我们看到了int,现在明确了它是一个指向int类型变量的指针.
4.最后看到了const限定词,于是我们把指针类型(?)完善为 指向const int 类型变量的指针.
总结:ptr是一个指向整型常量的指针常量.
功能:ptr不可以更改所值对象(ptr本身的值),也不可以通过*ptr改变所指对象的值.
- “常量引用”
int val = 3;
const int &ref = val; //从前面的知识我们知道这是一个底层const,通过引用ref不可以
//修改val的值
处理类型
类型别名
- typedef及复合类型
//Example
typedef double wages; //wages是double的同义词
typedef wages base,*p; //base是wages\double的同义词,p是double* 的同义词
复合类型
//Example
typedef char *char_ptr; //char_ptr是指向char类型的指针类型
char c = 'a';
char_ptr pointer = &c;
typedef const int hard_int; //hard_int是const int 类型
hard_int val = 10;
val = 5; //编译出错 val是由hard_int 定义的 const int 类型
- C++11新方法:别名声明
using MC = MyClass; //MyClass是已定义的类,MC是它的同义词
auto类型说明符
- auto会忽略顶层cosnt
int a,b;
int *const c_ptr = &a;
auto auto_type = c_ptr;
c_ptr = &b; //编译失败,c_ptr有顶层const
auto_type = &b; //合法,auto类型忽略了顶层const
如果希望推断出的auto类型带有顶层const,需要明确指出
const auto auto_type = c_ptr;
auto_type = &a; //编译失败,auto_type被明确指定了顶层const
decltype类型指示符 C+11
decltype的作用
需要使用某个变量(表达式)的类型,却不希望使用它作为初始值
const int ci = 0, &cj = ci;
decltype(ci) x = 0; //正确,x是const int类型
decltype(cj) y ; //错误,y是const int&类型,必须指定初始值
- decltype与引用
decltype( 表达式)得到的类型就是表达式的类型
int i = 0, &ri = i, *pi = &i; decltype(ri+0)b; ///正确,ri是对int的引用,表达式ri+0结果的类型是int decltype(*pi)c; //错误,*pi是对指针的解引用,故*pi的类型是 int&,需要对其初始化
decltype((variable))永远是引用类型,因为:
如果给变量加上一层括号,则编译器将(variable)视作一个表达式. 变量是一种可以作为赋值语句左值的特殊表达式,所以decltype就会得到引用类型int i = 0; decltype(i) a; //a是int类型 decltype((i)) b = i; //b是int &类型