逐个使用C++11新特性
C++11
auto & decltype
auto:根据变量初始值来推导变量类型,并用右值初始化变量。
1 int main() 2 { 3 map<string, vector<string>> family; 4 family.insert(pair<string, vector<string>>("陈", {"澄", "尘"})); 5 family.insert(pair<string, vector<string>>("朱", {"珠", "茱"})); 6 for(const auto &mp : family) 7 { 8 cout << mp.first << endl; 9 for(const auto &str : mp.second) 10 cout << str << " "; 11 cout << endl; 12 } 13 return 0; 14 }
decltype:从表达式推导出类型,并将变量定义为该类型,但不用表达式的值初始化该变量。
这里要注意下:decltype(i)--是i的类型,而decltype((i))就是引用了。就像上面例子中的x 就是int &x;
右值引用
新标准在拷贝构造函数、拷贝赋值运算符和析构函数之外,还增加了移动构造函数和移动赋值运算符,而这二位就需要右值引用的支持。
1. 延长将亡值的生命。
1 //右值引用 2 int a = 5; 3 int &b = a; 4 int &&bb = 89;//右值引用只能绑定将亡值 5 //int &&bb = a;//错,a是左值(持久值) 6 a = std::move(bb);//右值引用移动 7 8 cout << "引用:" << b << endl; 9 cout << "右值引用:" << bb << endl; 10 cout << "移动: " << a << endl;
&&bb = 999;//错,类似左值引用,不可二次赋值
&b = 888;//错
我们居然输出了89,要知道,右值只是临时量,用完就扔的。
2. 用于移动(构造)函数
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 6 class test 7 { 8 public: 9 test(); 10 ~test();
void push(const int& i); 11 void push(int&& i) 12 { 13 bar = std::move(i);//std::move(右值引用)实现移动 14 } 15 private: 16 int bar; 17 }; 18 19 int main() 20 { 21 int a = 1; 22 test t; 23 t.push(1); 24 //t.push(a);错误无法将右值绑定到左值 25 26 return 0; 27 }
范围for循环
统计字符
1 string str = "No pain, no gain! Everyone need to struggle for himself."; 2 decltype(str.length()) count = 0, count1 =0; 3 for (auto i : str) 4 if (ispunct(i)) 5 ++count; 6 else 7 ++count1; 8 cout << "字符串长度:" << str.size() << endl; 9 cout << "标点字符的个数:" << count << endl; 10 cout << "其他字符的个数:" << count1 << endl;
改写字符
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 int main() 6 { 7 string str("No pain, no gain! Everyone need to struggle for himself."); 8 cout << str << endl; 9 10 for (auto &c : str) 11 c = toupper(c);//小写换大写 12 13 cout << str << endl;; 14 return 0; 15 }
去除字符
//去除标点 1
#include <iostream> 2 #include <string> 3 using namespace std; 4 5 int main() 6 { 7 string input, res = ""; 8 while (cin >> input) 9 { 10 for (auto c : input) 11 if (!ispunct(c)) 12 res += c; 13 cout << res << endl; 14 res = ""; 15 } 16 }
智能指针
std::weak_ptr & std::shared_ptr
lambda表达式·λ
先看它怎么用
例1
1 //惯用法 2 //[捕获外部变量](参数列表)->返回类型{ 函数体(别忘记";")} 3 auto str = "I want you!"; 4 auto f = [](string str)->int { return str.size(); }; 5 cout << f(str) << endl; 6 7 int m = 999; 8 //捕获参数---值捕获 9 auto getValue = [m] {cout << m << endl; }; 10 getValue(); 11 //捕获参数---引用捕获 12 auto getValue1 = [&m] {cout << m << endl; }; 13 getValue1(); 14 15 //捕获参数---隐式值捕获 16 auto getValue2 = [=] {cout << m << endl; }; 17 getValue2(); 18 19 //捕获参数---隐式引用捕获 20 auto getValue3 = [&] { 21 cout << m << endl; 22 cout << "修改:" << ++m << endl; 23 }; 24 getValue3(); 25 26 int num[5] = { 1, 5, 8, 2, 3 }; 27 sort(num, num + 5, [](const int a, const int b) ->bool {return a > b; }); 28 29 for (auto i : num) 30 cout << i << " ";
例子补充:
1 int main() 2 { 3 //lambda表达式 4 //1.标准写法[捕获函数内局部变量列表] (传入参数列表) ->return type {function body;} ; 5 auto fc = []()->int { 6 return 100; 7 }; 8 cout << "1.标准写法\n" << fc() << endl; 9 10 //2.带传参数 11 auto f = [](int a, int b) { 12 return a + b; 13 }; 14 cout << "2.带传参数\n" << f(4, 5) << endl; 15 16 //3.捕获变量值 17 int param = 100; 18 auto ff = [param](int b){ 19 return param + b; 20 }; 21 cout << "3.捕获变量值\n" << ff(1) << endl; 22 23 //4.捕获变量引用 24 int param2 = 999; 25 auto ff2 = [¶m2](int b){ 26 param2 += 1; 27 return param2 + b; 28 }; 29 cout << "4.捕获变量引用\n" <<ff2(1) << endl; 30 cout << param2 << endl; 31 32 //4.当作算法函数谓词,例修改sort排序降序 33 vector<int> vec = {1, 3, 5, 2, 4, 9}; 34 sort(vec.begin(), vec.end(), [](int a, int b){ return a > b;}); 35 for(auto i : vec) 36 cout << i << " "; 37 38 //隐式引用捕获:即默认局部变量都是引用类型,可以在λ体内修改,也可以在参数捕获列表中指定某些参数只是值捕获,否则全部默认引用捕获 39 string str = "lambda"; 40 string str2 = " is good candy!"; 41 auto addStr = [&]{ 42 str = "lambda really"; 43 return str + str2; 44 }; 45 cout << addStr() << " " << str << endl; 46 return 0; 47 }
它的优势在哪里?又或者说为什么要用它呢?
再看一个例子
例2
1 //多线程 2 for (int i = 0; i < 5; ++i) 3 { 4 std::thread t([i] { cout << i << endl; });//<thread> 5 t.detach(); 6 }
从上面的多个例子看来,我们可以很方便的实现“函数内的函数定义和使用”,即函数嵌套【例1】,这样一来就不用再在外部定义函数,然后才能使用【例2】。甚至,它连函数名都可以不要,就像上面的sort函数中的用法一样。极大的简化了我们的代码,可读性也增强了许多,不用再回到定义处推敲了。😊