前言:前面涉及C++11的知识点我们补充讲解过,现在这篇博客我们正式讲解C++11。
我尽量活成我想成为的模样,而不是某些人口中的‘他’。
我们每个人都在跟自己的业力对抗,都想努力变好,可是这个世界本身就是矛盾的。
愿吾之愿力能护持汝生生世世,不被世俗沉沦,看破诸法实相
C++11简介
统一的列表初始化
{}初始化
创建对象时也可以使用列表初始化方式调用构造函数初始化
class Date { public: Date(int year, int month, int day) :_year(year) ,_month(month) ,_day(day) { cout << "Date(int year, int month, int day)" << endl; } private: int _year; int _month; int _day; }; int main() { Date d1(2022, 1, 1); // old style // C++11支持的列表初始化,这里会调用构造函数初始化 Date d2{ 2022, 1, 2 }; //直接调用构造 Date d3 = { 2022, 1, 3 }; //这里先调用构造生成一个初始化的临时对象,然后拷贝构造给对象 return 0; }单参数列表初始化可省略列表
class A { public: //explicit A(int x, int y) explicit可以防止隐式类型转换,使列表初始化失效 A(int x, int y) :_x(x) ,_y(y) {} A(int x) :_x(x) ,_y(x) {} private: int _x; int _y; }; int main() { A aa1 = 1; A aa2={1}; //都是先调用构造生成临时对象,然后拷贝构造 return 0; }赋值重载运算符也支持使用列表,A a,a={1}或a=1,先构造临时对象然后调用赋值运算符。
std::initializer_list
int main() { vector<int> v = { 1,2,3,4 }; //vector<int> v{ 1,2,3,4 }; //vector<int> v({1,2,3,4}); list<int> lt = { 1,2 }; // 1.这里{"sort", "排序"}会先初始化构造一个pair对象 // 2.initializer_list<pair>的构造 map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} }; // 使用大括号对容器赋值 v = {10, 20, 30}; return 0; }namespace bit { template<class T> class vector { public: typedef T* iterator; vector(initializer_list<T> l) { _start = new T[l.size()]; _finish = _start + l.size(); _endofstorage = _start + l.size(); iterator vit = _start; typename initializer_list<T>::iterator lit = l.begin(); while (lit != l.end()) { *vit++ = *lit++; } //for (auto e : l) // *vit++ = e; } vector<T>& operator=(initializer_list<T> l) { vector<T> tmp(l); std::swap(_start, tmp._start); std::swap(_finish, tmp._finish); std::swap(_endofstorage, tmp._endofstorage); return *this; } private: iterator _start; iterator _finish; iterator _endofstorage; }; }声明
auto
decltype
template<class T> class B { public: T* New(int n) { return new T[n]; } }; auto func1() { list<int> lt; auto ret = lt.begin(); return ret; } int main() { list<int>::iterator it1; // typeid推出时一个单纯的字符串 cout << typeid(it1).name() << endl; // // 不能用来定义对象 // //typeid(it1).name() it2; // 可以用来定义对象 decltype(it1) it2; cout << typeid(it2).name() << endl; auto it3 = it1; cout << typeid(it3).name() << endl; auto ret3 = func1(); B<decltype(ret3)> bb1; B<decltype(it3)> bb2; //B<std::list<int>::iterator> bb2; // auto和decltype有些地方增加代码读起来难度 return 0; }nullptr
范围for循环
在前文我们已经具体讲解了,这里我们补充一点
int main() { map<string, string> dict2 = { {"sort", "排序"}, {"insert", "插入"} }; for (auto& [x,y] : dict2) { cout << x << ":" << y << endl; //x += '1'; y += '2'; } for (auto [x, y] : dict2) { cout << x << ":" << y << endl; } pair<string, string> kv1 = { "sort", "排序" }; auto [x, y] = kv1; return 0; }智能指针
STL中一些变化
http://www.cplusplus.com/reference/vector/vector/emplace_back/
http://www.cplusplus.com/reference/vector/vector/push_back/
http://www.cplusplus.com/reference/map/map/insert/
http://www.cplusplus.com/reference/map/map/emplace/
右值引用和移动语义
我的总结:
左值:可以取地址的
右值:不可以取地址的,分为内置类型字面常量,匿名对象/变量,临时对象/变量
左值和右值都存在地址,只是左值能取地址,而右值不能取地址
右值分为纯右值(字面常量)和将亡值(匿名对象/变量,临时对象/变量)
个人猜测:右值引用引用字面常量时,会生成临时变量/对象
int&& p=10;// int b=10; int&& p= b; b是临时变量
class A
{
public:
A(int a1, int a2)
:_a1(a1)
, _a2(a2)
{}private:
int _a1;
int _a2;
};A&& p = { 1,2 };// A b(1,2); A&& p= b; b是临时对象