逐个使用C++11新特性

Posted yocichen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逐个使用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::unique_ptr

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 = [&param2](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函数中的用法一样。极大的简化了我们的代码,可读性也增强了许多,不用再回到定义处推敲了。

以上是关于逐个使用C++11新特性的主要内容,如果未能解决你的问题,请参考以下文章

C# 11 的这个新特性,我愿称之最强!

面试必问的C++11新特性代码实践

C++11新特性总结

C# 11 的这个新特性,我愿称之最强!

C++11 现代C++风格的新元素--简介

11年 C# 4.0四大新特性代码示例与解读