统一初始化方法

  1. int arr[3]{1,2,3};
  2. vector<int> iv{1, 2, 3};
  3. map<int, string> mp{{1, "a"}, {2, "b"}};
  4. string str{"Hello World"};
  5. int * p = new int[20]{1,2,3};
  6. struct A {
  7. int i, j; A(int m, int n):i(m), j(n){ }
  8. };
  9. A func(int m, int n) { return {m, n}; }
  10. int main() {
  11. A * pa = new A {3, 7};
  12. return 0;
  13. }

成员变量默认初始值

  1. class B {
  2. public:
  3. int m = 1234;
  4. int n;
  5. };
  6. int main() {
  7. B b;
  8. cout << b.m << endl; // 1234
  9. return 0;
  10. }

auto关键字

  1. auto i = 100; // i 是 int
  2. auto p = new A(); // p 是 A *
  3. auto k = 34343LL; // k 是 longlong
  4. map<string,int,greater<string> > mp;
  5. for(auto i = mp.begin(); i != mp.end(); ++i)
  6. cout << i->first << "," << i->second;
  7. // i的类型是: map<string, int, greater<string> >::iterator
  8. class A {};
  9. A operator + (int n, const A & a) {
  10. return a;
  11. }
  12. template <class T1, class T2>
  13. auto add(T1 x, T2 y) -> decltype(x+y) {
  14. return x + y;
  15. }
  16. auto d = add(100, 1.5); // d 是 double d = 101.5
  17. auto k = add(100, A()); // k是A类型

decl关键字

求表达式的类型

  1. int i;
  2. double t;
  3. struct A {double x;};
  4. const A * a = new A();
  5. decltype(a) x1; // x1 is A *
  6. decltype(i) x2; // x2 is int
  7. decltype(a->x) x3; // x3 is double
  8. decltype((a->x)) x4 // x4 is double &

智能指针shared_ptr

image.png

  1. #include <memory>
  2. #include <iostream>
  3. using namespace std;
  4. struct A
  5. {
  6. int n;
  7. A(int v = 0) : n(v) {}
  8. ~A() { cout << n << " destructor" << endl; }
  9. };
  10. int main()
  11. {
  12. shared_ptr<A> sp1(new A(2)); // sp1托管A(2)
  13. shared_ptr<A> sp2(sp1); // sp2也托管A(2)
  14. cout << "1) " << sp1->n << "," << sp2->n << endl;
  15. // 输出 1) 2,2
  16. shared_ptr<A> sp3;
  17. A *p = sp1.get(); // p 指向 A(2)
  18. cout << "2) " << p->n << endl; // 输出 2
  19. sp3 = sp1; // sp3也托管A(2)
  20. cout << "3) " << (*sp3).n << endl; // 输出2
  21. sp1.reset(); // sp1放弃托管A(2)
  22. if (!sp1) // 如果sp1没有托管任何指针
  23. cout << "4) sp1 is null" << endl; // 输出
  24. A *q = new A(3);
  25. sp1.reset(q); // sp1托管A(3)
  26. cout << "5) " << sp1->n << endl; // 输出 3
  27. shared_ptr<A> sp4(sp1); // sp4托管A(3)
  28. shared_ptr<A> sp5;
  29. // sp5.reset(q); 不妥,会导致程序出错
  30. sp1.reset(); // sp1放弃托管A(3)
  31. cout << "before end main" << endl;
  32. sp4.reset();
  33. cout << "end main" << endl;
  34. return 0; // 程序结束,会delete A(2)
  35. }
  36. /******************** 输出
  37. 1) 2,2
  38. 2) 2
  39. 3) 2
  40. 4) sp1 is null
  41. 5) 3
  42. before end main
  43. 3 destructor
  44. end main
  45. 2 destructor
  46. ***********************/

使用注意事项

  1. #include <iostream>
  2. #include <memory>
  3. using namespace std;
  4. struct A{
  5. ~A( cout << "~A" << endl;)
  6. };
  7. int main() {
  8. A * p = new A();
  9. shared_ptr<A> ptr(p);
  10. shared_ptr<A> ptr2;
  11. ptr2.reset(p); // 并不增加ptr中对p的托管计数
  12. cout << "end" << endl;
  13. return 0;
  14. }
  15. /***************** 输出
  16. end
  17. ~A
  18. ~A
  19. 之后程序崩溃,因
  20. p被delete两次
  21. ******************/

nullptr

  1. #include <memory>
  2. #include <iostream>
  3. using namespace std;
  4. int main() {
  5. int * p1 = NULL;
  6. int * p2 = nullptr;
  7. shared_ptr<double> p3 = nullptr;
  8. if(p1 == p2)
  9. cout << "equal 1" << endl;
  10. if(p3 == nullptr)
  11. cout << "equal 2" << endl;
  12. if(p3 == p2); // error 对象类型不同
  13. if(p3 == NULL)
  14. cout << "equal 4\n";
  15. bool b = nullptr; // b = false
  16. int i = nullptr; // error nullptr不能自动转换为整型
  17. }
  18. /******************* 输出
  19. equal 1
  20. equal 2
  21. equal 4
  22. ********************/

基于范围的for循环

注意 for 中参数类型是否写引用

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. struct A
  5. {
  6. int n;
  7. A(int i) : n(i) {}
  8. };
  9. int main()
  10. {
  11. int ary[]{1, 2, 3, 4, 5};
  12. for (int &e : ary)
  13. e *= 10;
  14. for (int e : ary)
  15. cout << e << ",";
  16. cout << endl;
  17. vector<A> st(ary, ary + 5);
  18. for (auto &it : st)
  19. it.n *= 10;
  20. for (A it : st)
  21. cout << it.n << ",";
  22. cout << endl;
  23. return 0;
  24. }
  25. /******************** 输出
  26. 10,20,30,40,50,
  27. 100,200,300,400,500,
  28. *********************/

右值引用和move语义

image.png

  1. #include <iostream>
  2. #include <string>
  3. #include <cstring>
  4. using namespace std;
  5. class String
  6. {
  7. public:
  8. char *str;
  9. String() : str(new char[1]) { str[0] = 0; }
  10. String(const char *s)
  11. {
  12. str = new char[strlen(s) + 1];
  13. strcpy(str, s);
  14. }
  15. String(const String &s)
  16. {
  17. cout << "copy constructor called\n";
  18. str = new char[strlen(s.str) + 1];
  19. strcpy(str, s.str);
  20. }
  21. String &operator=(const String &s)
  22. {
  23. cout << "copy operator= called\n";
  24. if (str != s.str)
  25. {
  26. delete[] str;
  27. str = new char[strlen(s.str) + 1];
  28. strcpy(str, s.str);
  29. }
  30. return *this;
  31. }
  32. // move constructor
  33. String(String &&s) : str(s.str)
  34. {
  35. cout << "move constructor called\n";
  36. s.str = new char[1];
  37. s.str[0] = 0;
  38. }
  39. // move assignment
  40. String &operator=(String &&s)
  41. {
  42. cout << "move operator= called\n";
  43. if (str != s.str)
  44. {
  45. delete[] str;
  46. str = s.str;
  47. s.str = new char[1];
  48. s.str[0] = 0;
  49. }
  50. return *this;
  51. }
  52. ~String() { delete[] str; }
  53. };
  54. template <class T>
  55. void MoveSwap(T &a, T &b) // 有意的避免深拷贝
  56. {
  57. T tmp(move(a)); // std::move(a)为右值,这里会调用 move constructor
  58. a = move(b); // move(b)为右值,因此这里会调用 move assignment
  59. b = move(tmp); // move(tmp)为右值,因此这里会调用 move assignment
  60. }
  61. int main()
  62. {
  63. // String &r = String("this"); // error
  64. String s;
  65. s = String("ok"); // String("ok")是右值
  66. cout << "******" << endl;
  67. String &&r = String("this");
  68. cout << r.str << endl;
  69. String s1 = "hello", s2 = "world";
  70. MoveSwap(s1, s2);
  71. cout << s2.str << endl;
  72. return 0;
  73. }
  74. /**************** 输出
  75. move operator= called
  76. ******
  77. this
  78. move constructor called
  79. move operator= called
  80. move operator= called
  81. hello
  82. *****************/

image.png

可移动但不可复制的对象

  1. struct A {
  2. A(const A & a) = delete;
  3. A(const A && a) {cout << "move" << endl;}
  4. A() {};
  5. };
  6. A b;
  7. A func() {
  8. A a;
  9. return a;
  10. }
  11. void func2(A a) {}
  12. int main() {
  13. A a1;
  14. A a2(a1); // compile error
  15. func2(a1); // compile error
  16. func();
  17. return 0;
  18. }

无序容器(哈希表)

map 的完全一样,只是底层使用的哈希表实现

  1. #include <iostream>
  2. #include <unordered_map>
  3. #include <string>
  4. using namespace std;
  5. int main()
  6. {
  7. unordered_map<string, int> turingWinner; // 图灵奖获奖名单
  8. turingWinner.insert(make_pair("Dijkstra", 1972));
  9. turingWinner.insert(make_pair("Scott", 1976));
  10. turingWinner.insert(make_pair("Wilkes", 1967));
  11. turingWinner.insert(make_pair("Hamming", 1968));
  12. turingWinner["Ritchie"] = 1983;
  13. string name;
  14. cin >> name;
  15. unordered_map<string, int>::iterator p = turingWinner.find(name);
  16. if (p != turingWinner.end())
  17. cout << p->second;
  18. else
  19. cout << "Not found.\n";
  20. return 0;
  21. }

正则表达式

  1. #include <iostream>
  2. #include <regex>
  3. using namespace std;
  4. int main()
  5. {
  6. regex reg("b.?p.*k");
  7. cout << regex_match("bopggk", reg) << endl; // 输出1,表示匹配成功
  8. cout << regex_match("boopgggk", reg) << endl; // 输出0,表示匹配失败
  9. cout << regex_match("b pk", reg) << endl; // 输出1,表示匹配成功
  10. regex reg2("\\d{3}([a-zA-z]+).(\\d{2}|N/A)\\s\\1");
  11. string correct = "123Hello N/A Hello";
  12. string incorrect = "123Hello 12 hello";
  13. cout << regex_match(correct, reg2); // 输出1,匹配成功
  14. cout << regex_match(incorrect, reg2); // 输出0 匹配失败
  15. return 0;
  16. }

lambda表达式

image.png

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int x = 100, y = 200, z = 300;
  6. cout << [](double a, double b) { return a + b; }(1.2, 2.5) << endl;
  7. auto ff = [=, &y, &z](int n) {
  8. cout << x << endl;
  9. y++;
  10. z++;
  11. return n * n;
  12. };
  13. cout << ff(15) << endl;
  14. cout << y << "," << z << endl;
  15. return 0;
  16. }
  17. /****************** 输出
  18. 3.7
  19. 100
  20. 225
  21. 201,301
  22. *******************/
  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. int main()
  5. {
  6. int a[4] = {4, 2, 11, 33};
  7. sort(a, a + 4, [](int x, int y) -> bool { return x % 10 < y % 10; });
  8. for_each(a, a + 4, [](int x) { cout << x << " "; });
  9. return 0;
  10. }
  11. /************ 输出
  12. 11 2 33 4
  13. *************/
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. using namespace std;
  5. int main()
  6. {
  7. vector<int> a{1, 2, 3, 4};
  8. int total = 0;
  9. for_each(a.begin(), a.end(), [&](int &x) { total += x; x *= 2; });
  10. cout << total << endl; // 输出 10
  11. for_each(a.begin(), a.end(), [](int x) { cout << x << " "; });
  12. return 0;
  13. }
  14. /************** 输出
  15. 10
  16. 2 4 6 8
  17. ***************/

image.png