目录
列表初始化
定义:无论是在初始化对象还是为对象赋新值时,将想要输入的值放入花括号就能为这个对象赋新值或初始化它,这就叫做列表初始化。
//普通
int num = 0; //√
int num(0) //√
//列表初始化:
int num = {0} //√
//省略=也可以
int num{0} //√
不过这种初始化有一个重要特点:
如果我们使用列表初始化 且 初始值存在丢失信息的风险时 编译器将报错
例如:
double b = 3.1415926; //此时编译器报错,因为double类型转为int有丢失的风险 int a{b}; int c = {b}; //但如果是普通初始化,虽然确实会丢失数据,但是不会报错 int a = b; //a = 3 int c(b); //c = 3
列表初始化支持的类型
列表初始化支持内置类型、自定义类型的单个对象初始化,对于自定义类型的多个对象初始化,我们需要用到一个系统自定义的类模板:initializer_list,该类模板中有三个方法:begin()、end()、以及size()。
initializer_list中存储的都是常量值,不能改变,我们可以传一个initializer _list<模板类型>来遍历它进行赋值,来实现自定义类型的多个对象初始化。
like:
#include <initializer_list>
template<class V>
class MyVector
{
public:
MyVector(initializer_list<V> l):_capacity(l.size()),_size(0)
{
_array = new V[_capacity];
//把传进来的值赋进去
for(int i = 0; i < l.size();i++)
{
array[i] = l[i]
}
}
private:
T* _array;
size_t _size;
size_t _capacity;
};
变量类型推导
定义:变量类型推导就是在不明确需要用一个什么类型来接收等号右边的值的时候,编译器可以自己推导右边值的类型的一种机制。在C++11中,我们可以使用auto、decltype来进行变量类型推导。
auto
auto让编译器通过初始值来推算变量的类型,也就是auto定义的变量必须有初始值
//通过val1和val2相加的结果可以推断one的类型
auto one = val1 + val2;
//可以在一条语句中声明多个变量(!必须有初始值!)
auto i = 0,*p = i; //正确 i是整型 p是整型指针
auto sz = 0,pi = 3.14 //错误 sz和p类型不一致
auto时如果是引用做初始值,那么auto推出的类型实际上是引用对象的类型,而不是这个引用,例:
int a = 1; int& b = a; auto c = b; //此时c是int类型,而不是int&
当然如果auto后面加上引用符号,也可以生成引用
auto &b = a; //此时b是a的引用
auto一般会忽略顶层const,但是会保留底层const(关于顶层底层const会另作说明)
我们来看一段代码理解:
int a = 1;
const int ca = a;
const int& cr = ca;
auto b = ca; //b是一个int 而不是const int
auto c = cr; //同上(因为cr也只是一个别名)
auto d = &a; //d是一个整型指针
auto e = &ca; //e是一个指向const int的指针(此时为底层const)
ps:范围for也是C++11新增加的特性,用auto实现~
vector<int> a = {1,2,3,4,5,6,7,8,9}; //遍历一整个vector for(auto e:a) { cout << e << ' '; } cout << endl;
输出为:1 2 3 4 5 6 7 8 9
decltype
如果想要用表达式推断出的类型作为一个要定义的变量的类型,但是又不想初始化。我们可以使用decltype,它可以选择并返回操作数的数据类型,在这个过程中,编译器只是对表达式进行分析并得到它的类型,而没有实际的计算这个表达式
decltype(f()) sum = x; //sum的类型就是函数f的返回类型
decltype和auto更多的不同之处在于,decltype不会对const或者引用做过多处理,可以看下面的代码加深理解:
int a = 1;
const int ca = a;
const int& cr = ca;
decltype(ca) b = ca; //b是一个const int
decltype(cr) c = b; //c是一个const int& (因为cr也是)
decltype(cr) d; //此时的d错误,因为它是一个引用类型,引用类型必须初始化
如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型
例如:
//r是一个int引用类型 decltype(r+0) a // 此时a是一个int而不是int&
显然r+0的表达式的结果会是一个具体值,而不是引用。
ps:decltype中有个很容易出错的地方
如果decltype里面的值单独加上一对圆括号,那么编译器就会把这个圆括号当成一个表达式。变量是一种可以作为赋值语句左值存在的特殊表达式,所以此时decltype的类型会变成引用。
int i = 1; decltype((i)) a; //此时a的类型是int&,编译器会报错,因为没有初始化 decltype(i) b; //此时b的类型是int(未初始化)