1,统一的初始化方法
1,定义变量:如vector <int> a {1,2,3,4};
2,创建对象:当类A的构造函数有两个参数时,A的实例化: A a {1,2};
3,返回值:当返回值类型是 vector<int>时,return {1,2,3,4,5,6,7};
2,auto关键字
1, 使用auto定义变量,必须初始化 ,在编译阶段由编译器推导得来, auto声明的变量的实际的类型,因此auto并非类型,
而是类型声明的占位符,编译器会在编译期间将auto转换成实际的类型。
2,auto的优势:
1,复杂类型变量声明时的简化,
如:vector<int> ::iterator it =v.begin();
auto it=v.begin();
2,免除变量声明时对于类型的选择,避免选择错误
const float pi = 3.14f;
double radis = 2.0;
auto c = 2 * pi * radis;
3,auto的自适应性能够在一定程度上支持泛型编程( 编写与类型无关的逻辑代码,是代码复用的一种手段 )
3,auto的使用细则
1,与指针和引用的联系
int x = 10;
auto a = &x;
auto* b = &x;
auto& c = x;
auto 和 auto* 无区别 编译器推导出来什么类型就是什么类型
但是若想要推导出来的类型是引用类型,那么就必须使用 auto&
2,与const一起使用
用const变量去初始化一个auto变量,auto变量依然是可以被修改的,说明
auto变量并不能从表达式中带走const限制
3,当一行声明多个auto变量时,多个变量的类型必须是完全一致的。
4. auto不能推导的场景: 形 非 组 模
auto不能作为函数的形参类型
auto不能定义类的非静态成员变量
auto不能直接用来声明数组 实例化模板时不能使用
auto作为模板参数
3,decltype关键字
1,前面讲的auto,用于通过一个表达式在初始化时期确定变量的具体类型,auto修饰的变量必须初始化,
也即是必须得定义变量,如果不需要或者不能定义变量,却想要得到类型该怎么办呢?
C++11新增了一个关键字decltype,用于在编译时期推导出一个表达式的类型,而不用初始化,
其语法格式有点像sizeof:decltype(expr) 于sizeof一样,decltype推导表达式类型也是在编译时期就完成的,
并不会真正的计算表达式的值。
- 2 ,decltype(expr)的推导规则如下:
1、expr是标识符,类访问表达式,decltype(expr)和expr的类型保持一致。
int n = 0; decltype(n) a = n; //a -> int expr是标识符
decltype(Foo::number) c = 0; //const int expr是类访问表达式,假设类Foo中变量number的类型是const int
2、expr是函数调用,decltype(expr)和返回值类型一致。
decltype(func()) c1 = 0; //c1 -> int expr是函数调用,且函数返回值是int
3、expr是一个左值,则decltype(expr)是expr类型的左值引用,否则和expr类型一致。
左值表达式表示的是一个对象的身份(在内存中的空间),而右值表达式表示的是对象的值(内容)。
decltype((foo.x)) b = a; // b-> const int & 给 foo.x这个类访问表达式加上()后就变成了左值
X本来是const int 形,得到的类型就是const int &
decltype(n += m) d = c; //d -> int & n+=m也是一个左值,所以得到的类型是 int &
4,基于范围的的for循环
int main()
{ int array[] = { 1, 2, 3, 4, 5 };
for (auto& e : array)
e *= 2;
for (auto e : array)
cout << e << " ";
return 0;
}
for循环后的括号有冒号”:”分为两部分,第一部分是范围内用于迭代的 变量,第二部分则表示被迭代的范围。
它与普通循环类似,可以用 continue来结束本次循环,也可以用break来跳出整个循环。
1,for循环迭代的范围是确定的 对于数组而言就是数组第一个元素和最后一个元素的范围;
对于类来 说,应该提供begin和end方法,begin和end就是for循环迭代的范 围
2,迭代的对象要实现++和==操作符 注意:基于范围的for循环使用于标准库的容器时,
如果使用auto来声明迭代的对象,那么这个对象不会是迭代器对象
如:std::vector v{ 1, 2, 3, 4, 5 };
for (auto e : v)
cout << e << " "; // e为解引用后的对象 ,不是迭代器
5.default 关键字
假设你为类定义了构造函数,那么类就不会自动提供默认的构造函数了,然而,
如果你仍然想使用类提供的默认版本,那么可以使用default关键字:
意思就是想用默认函数还不想定义,就直接让默认函数=default
6,delete关键字
禁止编译器生成默认函数
7,final关键字
1,final修饰虚函数,子类将不能对虚函数重写
2,final修饰类,类将不能被继承
8,override
override修饰函数时,在重写时如果出现拼写错误,类型与基类不同,重写了 基类的非虚函数等,
override可以保证编译器辅助的做一些检查。
注意:final/override也可以定义为正常的变量名,只有出现在类和函数 之后才表示不能被继承或者是否正确重写。
这样设计C++98的代码就可以 通过编译,但是建议尽可能避免这样的变量名称。