## 今天学了什么
今天学习C++11的一些特性内容。
## 使用auto进行自动类型推导
①使用要求:使用auto声明变量必须初始化。
②语法:
auto 变量名=变量值;
* 注:
当变量不是指针或引用类型时,推导的结果不会保留const/引用;
当变量是指针或引用类型时,推导的结果会保留const/引用;
例:
const int a=10;
auto b=a; //b的数据类型为 : int
const int* b = &a;
auto c = b; // const int*
const int d = a;
auto &e=a; //const int &
③auto的限制
Ⅰ.不能作为函数参数使用(auto编译期行为,函数声明时编译器看不到实参,没办法推导类型)(C++14/17可以)
Ⅱ.不能用于类的非静态成员变量的初始化;
class Myarr{
public:
auto a=10; ✘
}
Ⅲ.不能定义数组;
int arr[]={1,2,3};
auto a[]=arr; ✘
auto a[]={1,1,2};✘
auto a=arr; ✔
auto a={1,2,3}; ✔
Ⅳ.无法使用auto推导模板参数类型(C++17可以 :Test t2=t;)
Test<double> t;
Test<auto> t2=t; ✘
④auto的应用场景
Ⅰ.用于遍历STL容器
for (auto &s : v)
{
cout << ++s << " ";
}
Ⅱ.调用相关模板函数
template<class T>
void func()
{
auto ret = T::get(); //不同类的同名get 成员函数
};
## 范围for循环
①语法:
for(声明变量:要遍历的对象){}
其中,要遍历的对象可以是表达式、容器、数组、初始化列表等。循环会依次取出对象中的每个元素,并绑定到声明的变量上,从而实现对元素的逐个访问。
根据实际需求,可以选择不同的变量声明方式:
- 可修改遍历:使用
auto &s,以引用方式绑定元素,循环体内对s的修改会直接反映到原容器中。 - 只读遍历:使用
const auto &s,以常量引用方式绑定元素,既避免拷贝开销,又保证循环体内不会意外修改原数据。
示例代码如下:
for (auto &s : v) //可修改
for (const auto &s : v) //只读
注:set/map容器,用auto &也不能修改key。
②普通for循环与范围for循环区别:
Ⅰ.
普通for遍历容器:
for(auto it=v.begin();it!=v.end();it++)
auto:vector<int>::iterator
范围for:
for(auto vec:v)
auto:value_type
Ⅱ.
普通for:可动态操作,可以修改值后不影响遍历结果;
范围for:后面的表达式只能访问一次,访问后就开始遍历,如果有动态操作,边界改变,但遍历还是以前的大小,影响遍历结果;
## using
C++11新增新特性:
①类型别名(对比typedef):
typedef int m_int; m_int a = 10; using n_int = int; n_int b = 11;②别名模板:
template<class T> struct Mymap { typedef map<int, T> new_map; }; template<class T> using n_map = map<int, T>;Mymap<int>::new_map m;
n_map<int> m2;
## override和final
注:加override关键字可以检查重写是否写对(写在函数后面)。
final:
①修饰函数:只能修饰虚函数,加了以后子类不能重写父类的该函数(写在函数后面)。
②修饰类:类无后代,不能用于子类继承(写在类后面 class Base final)。