C++ C++ 11 C++ 11 Lichermione 2026-09-15 2026-09-15 1.1字符串原始字面量 为了解决字符的转义和续行。 语法: “tag()tag” 注意 tag必须一样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> #include <string> using namespace std;int main () { string str1 = "lichermionex\r\n\t111" ; string str2 = R"(lichermionex\r\n\t111)" ; string str3 = R"name(lichermionex\r\n\t111)name" ; cout << "str1 : " << str1 << endl; cout << "str1 : " << str2 << endl; cout << "str1 : " << str3 << endl; return 0 ; }
运行结果
1 2 3 4 str1 : lichermionex 111 str1 : lichermionex\r\n\t111 str1 : lichermionex\r\n\t111
1.2 Long Long C++ 11 的新数据类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <iostream> using namespace std;int main () { long long num1 = 100LL ; unsigned long long num2 = 100ULL ; unsigned long long int num22 = 100ULL ; cout << "long long max:" << LLONG_MAX << endl; cout << "long long min:" << LLONG_MIN << endl; cout << "unsigned long long max:" << ULLONG_MAX << endl; char c = 6 ; long long d = c; unsigned long long aa = -1 ; cout << aa << endl; return 0 ; }
三个关键的宏:LLONG_MAX, LLONG_MIN, ULLONG_MAX。
补充知识: 整型家族的宏值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> #include <climits> using namespace std;int main () { cout << "SHRT_MAX:" << SHRT_MAX << endl; cout << "SHRT_MIN:" << SHRT_MIN << endl; cout << "USHRT_MAX:" << USHRT_MAX << endl << endl; cout << "INT_MAX:" << INT_MAX << endl; cout << "INT_MIN:" << INT_MIN << endl; cout << "UINT_MAX:" << UINT_MAX << endl <<endl; cout << "LONG_MAX:" << LONG_MAX << endl; cout << "LONG_MIN:" << LONG_MIN << endl; cout << "ULONG_MAX:" << ULONG_MAX << endl; cout << "LLONG_MAX:" << LLONG_MAX << endl; cout << "LLONG_MIN:" << LLONG_MIN << endl; cout << "ULLONG_MIN:" << ULLONG_MAX << endl; cout << "CHAR_BIT:" << CHAR_BIT << endl; }
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 SHRT_MAX:32767 SHRT_MIN:-32768 USHRT_MAX:65535 INT_MAX:2147483647 INT_MIN:-2147483648 UINT_MAX:4294967295 LONG_MAX:2147483647 LONG_MIN:-2147483648 ULONG_MAX:4294967295 LLONG_MAX:9223372036854775807 LLONG_MIN:-9223372036854775808 ULLONG_MIN:18446744073709551615 CHAR_BIT:8
1.3 初始化列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include <iostream> #include <string> using namespace std;class base { public : base (int num) :a (num) {} int a = 2 ; double b = 2.3 ; char ch = 'c' ; int a2{3 }; double b2{ 2.4 }; char ch2{'c' }; string str{ "licher" }; static int c1; static const double c2; static const char * c3; void print () const { cout << "a " << a << endl; } }; int base::c1 = 22 ;const double base::c2 = 22.5 ;const char * base::c3 = "lic" ;int main () { base b{ 1 }; b.print (); return 0 ; }
1.4 final 和 override 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> using namespace std;class base { public : virtual void test () { cout << "base" << endl; } }; class child final : public base { public : void test () final override { cout << "child" << endl; } }; int main () { child c; c.test (); return 0 ; }
final 修饰虚函数,此虚函数被继承下去后不能够被重写了。
final 修饰对象,此对象不能够被继承了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <iostream> using namespace std;class base { public : virtual void test () { cout << "base" << endl; } }; class child : public base{ public : void test () override { cout << "child" << endl; } }; int main () { return 0 ; }
检查继承下来的虚函数是否被重写了。
1.5右尖括号的对其 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> #include <map> #include <string> using namespace std;template <class T >class base { public : void print (const T& t) { auto it = t.begin (); while (it != t.end ()) { cout << it->first << ":" << it->second << endl; ++it; } } }; int main () { map<int , string> m; m.insert (make_pair (1 , "one" )); m.insert (make_pair (2 , "two" )); m.insert (make_pair (3 , "three" )); base<map<int , string>> c; c.print (m); return 0 ; }
自动类型推导
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> #include <map> #include <string> using namespace std;template <class T = long , class U = int >void print (T t = 'A' , U u = 'B' ){ cout << "t : " << t << " " << "u : " << u << endl; } int main () { print ('a' , 'b' ); print <char >('a' , 'b' ); print <int , char >('a' , 'b' ); print <char , int >('a' , 'b' ); print (); return 0 ; }
运行结果
1 2 3 4 5 t : a u : b t : a u : b t : 97 u : b t : a u : 98 t : 65 u : 66
没有指定需要推导的。默认的参数不能进行推导。
1.6静态断言 动态断言
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <cassert> using namespace std;char * createArray (int size) { assert (size > 0 ); char * array = new char [size]; return array; } int main () { char * buf = createArray (0 ); return 0 ; }
编译期间不会报错,运行期间会报错的。
静态断言
1 2 3 4 5 6 7 8 9 10 #include <cassert> using namespace std;int main () { static_assert (sizeof (char *) == 8 , "当前不是64位机器" ); return 0 ; }
编译期间进行常量表达式的检查。
1.7 noexcept 异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <iostream> #include <string> using namespace std;struct MyExcept { MyExcept (string str) :msg (str) { } string msg; }; void func () { try { throw MyExcept ("string exception !" ); } catch (int e) { cout << "throw value : " << e << endl; } catch (MyExcept e) { cout << "MyException : " << e.msg << endl; } } int main () { func (); cout << "hello world" << endl; return 0 ; }
noexcept
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <iostream> #include <string> using namespace std;struct MyExcept { MyExcept (string str) :msg (str) { } string msg; }; void func () noexcept (sizeof (char *) == 4 ) { throw MyExcept ("string exception !" ); } int main () { try { func (); } catch (MyExcept e) { cout << e.msg << endl; } return 0 ; }
noexcept不允许函数抛出异常的。 noexcept后面可以根常量表达式,用来控制函数是否抛出异常的。
1.8 数值转换成字符串 to_string函数重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #include <iostream> #include <string> using namespace std;int main () { int num1 = 1 ; unsigned int num2 = 2 ; long num3 = 3 ; unsigned long num4 = 4 ; long long num5 = 5 ; unsigned long long num6 = 6 ; float num7 = 7.0f ; double num8 = 2.3 ; long double num9 = 4.5L ; string str1 = to_string (num1); string str2 = to_string (num2); string str3 = to_string (num3); string str4 = to_string (num4); string str5 = to_string (num5); string str6 = to_string (num6); string str7 = to_string (num7); string str8 = to_string (num8); string str9 = to_string (num9); cout << "str1 : " << str1 << endl; cout << "str2 : " << str2 << endl; cout << "str3 : " << str3 << endl; cout << "str4 : " << str4 << endl; cout << "str5 : " << str5 << endl; cout << "str6 : " << str6 << endl; cout << "str7 : " << str7 << endl; cout << "str8 : " << str8 << endl; cout << "str9 : " << str9 << endl; return 0 ; }
运行结果
1 2 3 4 5 6 7 8 9 str1 : 1 str2 : 2 str3 : 3 str4 : 4 str5 : 5 str6 : 6 str7 : 7.000000 str8 : 2.300000 str9 : 4.500000
一共九个函数重载。int, long, long long, float, double, long double
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <iostream> #include <string> #include <stdexcept> #include <iomanip> using namespace std;int main () { int i = stoi ("123" ); long l = stol ("1234567890" ); long long ll = stoll ("1234567890123456789" ); unsigned long ul = stoul ("4000000000" ); unsigned long long ull = stoull ("18446744073709551615" ); cout << "i = " << i << '\n' ; cout << "l = " << l << '\n' ; cout << "ll = " << ll << '\n' ; cout << "ul = " << ul << '\n' ; cout << "ull = " << ull << '\n' ; string s = "123abc" ; size_t pos = 0 ; int n = stoi (s, &pos); cout << "n = " << n << ", pos = " << pos << ", rest = " << s.substr (pos) << '\n' ; cout << stoi ("ff" , nullptr , 16 ) << '\n' ; cout << stoi ("1010" , nullptr , 2 ) << '\n' ; cout << stoi ("0x1A" , nullptr , 0 ) << '\n' ; float f = stof ("3.14" ); double d = stod ("3.1415926535" ); long double ld = stold ("3.14159265358979323846" ); cout << setprecision (20 ); cout << "f = " << f << '\n' ; cout << "d = " << d << '\n' ; cout << "ld = " << ld << '\n' ; return 0 ; }
一共八个,int, long, long long, float ,double, long double 。 字符串,错误位置,进制
2.1 auto 基本的使用方法
使用:auto 变量名 = 变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include <iostream> using namespace std;int main () { int num{ 44 }; int & p1 = num; const int & p2 = num; volatile int & p3 = num; volatile const int & p4 = num; int * ptr1 = # const int * ptr2 = # volatile int * ptr3 = # volatile const int * ptr4 = # auto ref_p1 = p1; auto ref_p2 = p2; auto ref_p3 = p3; auto ref_p4 = p4; auto & ref_p12 = p1; auto & ref_p22 = p2; auto & ref_p32 = p3; auto & ref_p42 = p4; auto ref_ptr1 = ptr1; auto ref_ptr4 = ptr2; auto ref_ptr3 = ptr3; auto ref_ptr44 = ptr4; auto * ref_ptr12 = ptr1; auto * ref_ptr22 = ptr2; auto * ref_ptr32 = ptr3; auto * ref_ptr42 = ptr4; return 0 ; }
只有指针和引用 变量的const和volatil会被保留的
限制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <iostream> #include <string> #include <stdexcept> #include <iomanip> using namespace std;int main () { return 0 ; }
应用场景
STL遍历时候的迭代器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <iostream> #include <vector> #include <string> #include <map> using namespace std;void printMap () { map<int , string> m; m.insert (make_pair (1 , "one" )); m.insert (make_pair (2 , "two" )); m.insert (make_pair (3 , "three" )); m.insert (make_pair (4 , "four" )); m.insert (make_pair (5 , "five" )); auto it = m.begin (); while (it != m.end ()) { cout << it->first << " : " << it->second << endl; ++it; } } void printVector () { vector<char > v{ 'v' , 'e' , 'c' , 't' , 'o' , 'r' }; for (auto it = v.begin (); it != v.end (); ++it) { cout << *it << endl; } } int main () { printMap (); printVector (); return 0 ; }
模板函数的推导
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <iostream> #include <vector> #include <string> #include <map> using namespace std;class Base1 { public : static int get () { return 22 ; } }; class Base2 { public : static string get () { return "hello world" ; } }; template <class T>void func (void ) { auto ret = T::get (); cout << "ret : " << ret << endl; } int main () { func <Base1>(); func <Base2>(); return 0 ; }
2.2 decltype 基本使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <iostream> using namespace std;int main () { int num{ 44 }; int & p1 = num; const int & p2 = num; volatile int & p3 = num; volatile const int & p4 = num; int * ptr1 = # const int * ptr2 = # volatile int * ptr3 = # volatile const int * ptr4 = # decltype (p1) d_p1 = p1; decltype (p2) d_p2 = p2; decltype (p3) d_p3 = p3; decltype (p4) d_p4 = p4; decltype (ptr1) d_ptr1 = ptr1; decltype (ptr2) d_ptr2 = ptr2; decltype (ptr3) d_ptr3 = ptr3; decltype (ptr4) d_ptr4 = ptr4; decltype ((p1)) e_p1 = p1; decltype ((p2)) e_p2 = p2; decltype ((p3)) e_p3 = p3; decltype ((p4)) e_p4 = p4; decltype ((ptr1)) e_ptr1 = ptr1; decltype ((ptr2)) e_ptr2 = ptr2; decltype ((ptr3)) e_ptr3 = ptr3; decltype ((ptr4)) e_ptr4 = ptr4; return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <iostream> #include <vector> #include <string> #include <map> using namespace std;class Test { public : int a; string str; }; int main () { int a = 22 ; decltype (a) b = 99 ; decltype (a + 3.14 ) c = 55.3 ; decltype (a + b * c) d = 1.12 ; int num = 10 ; const int & numm2 = num; decltype (num) num3 = 55 ; decltype (numm2) num4 = num; decltype (Test::a) num6 = 555 ; decltype (Test::str) str = "licher" ; return 0 ; }
decltype(表达式) 变量名 = 初始值 。
函数返回值的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> #include <vector> #include <string> #include <map> using namespace std;int func_int () {}int & func_int_r () {}int && func_int_rr () {}const int func_const_int () {}const int & func_const_int_r () {}const int && func_const_int_rr () {}int main () { decltype (func_int ()) a = 22 ; decltype (func_int_r ()) b = a; decltype (func_int_rr ()) b = 33 ; decltype (func_const_int ()) c = 22 ; decltype (func_const_int_r ()) d = a; decltype (func_const_int_rr ()) e = 22 ; return 0 ; }
纯右值,字面量的时候就是一个常量。 去掉const
被()包围的时候或者是一个左值, decltype推导的时候是引用, 不能去掉 const和volatile限定符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <iostream> #include <vector> #include <string> #include <map> using namespace std;class Test { public : int a; string str; const static int b = 22 ; }; int main () { const Test test; decltype (test.a) a = 22 ; decltype (test.b) b = 22 ; decltype ((test.a)) a2 = a; int n = 0 ; int m = 0 ; decltype (n + m) c = 0 ; decltype (n = n + m) d = n; return 0 ; }
decltype的应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <iostream> #include <vector> #include <string> #include <list> #include <map> using namespace std;template <class T >class Container { public : void print (T& t) { for (_it = t.begin (); _it != t.end (); ++_it) { cout << "value:" << *_it << endl; } } private : decltype (T ().begin ()) _it; }; int main () { list<int > ls{ 1 , 2 ,4 ,5 ,6 ,7 ,8 , }; Container<list<int >> c; c.print (ls); Container<const list<int >> c1; c1. print (ls); return 0 ; }
推导出迭代器的类型
返回值类型后置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> #include <vector> #include <string> #include <list> #include <map> using namespace std;template <class T, class U>auto add (T t, U u) -> decltype (t + u) { return t + u; } int main () { cout << "ret1 :" << add (1 , 22.5 ) << endl; cout << "ret2 :" << add <int , double >(1 , 22.5 ) << endl; return 0 ; }
2.3范围for 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> #include <vector> #include <string> #include <list> #include <map> using namespace std;int main () { vector<int > v{ 1 , 3 , 4 , 5 , 6 , 7 ,6 }; for (const auto & e : v) { cout << "e : " << e << endl; } return 0 ; }
小细节
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <iostream> #include <vector> #include <string> #include <list> #include <map> using namespace std;int main () { map<int , string> m; m.insert (make_pair (1 , "one" )); m.insert (make_pair (2 , "two" )); m.insert (make_pair (3 , "three" )); m.insert (make_pair (4 , "four" )); for (auto & e : m) { cout << e.first << ":" << e.second << endl; } for (auto it = m.begin (); it != m.end (); ++it) { cout << it->first << ":" << it->second << endl; } return 0 ; }
set默认只读的。
2.4 nullptr 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <iostream> using namespace std;void func (char * p) { cout << "func(char*)" << endl; } void func (int p) { cout << "func(int p)" << endl; } int main () { func (NULL ); func (0 ); char * p1 = nullptr ; char * p2 = NULL ; func (p1); func (p2); void * ptr1 = NULL ; int * ptr2 = (int *)ptr1; void * ptr3 = nullptr ; double * ptr3 = nullptr ; char * ptr3 = nullptr ; return 0 ; }
C++的NULL就是定义的宏:0。
nullptr c++的万能指针。初始化的时候可以定义为任何类型的指针。
2.5 Lambda函数 1 2 3 4 5 6 7 8 9 // [capture] (params) opt->ret(body;}; []:不捕捉任何变量 [&]:引用的方式捕捉 [=]:捕获变量,作为副本在函数中使用。值拷贝 没有参数,可以省略 opt选项:mutable, exception mutable:修改拷贝的临时对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <iostream> using namespace std;void func (int x, int y) { int a = 1 ; int b = 2 ; [=, &x]()mutable { int c = a; int d = b; b++; cout << "b : " << b << endl; }(); cout << "b : " << b << endl; } int main () { func (1 , 2 ); return 0 ; }
lambda本身:仿函数。
捕获列表就是给匿名对象增加属性, mutable就是去掉函数的const。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <iostream> #include <functional> using namespace std;void func (int x, int y) { int a = 10 ; int b = 20 ; using ptr = void (*)(int ); ptr p1 = [](int x) { cout << "x : " << x << endl; }; p1 (22 ); function<void (int x)> f1 = [=](int x) { cout << "x : " << x << endl; }; f1 (33 ); function<void (int x)> f2 = bind ([=](int x) { cout << "x : " << x << endl; }, placeholders::_1); f2 (44 ); } int main () { func (1 , 2 ); return 0 ; }
3.1 constexpr constexpr修饰常量数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> #include <functional> using namespace std;void func () { const int a = 20 ; int arr[a] = { 0 }; } struct T { int a; };int main () { const int i = 1314 ; const int j = i + 1 ; constexpr int t1 = 44 ; constexpr int t2 = t1 + 33 ; constexpr T t1{ 222 }; constexpr T t2{ 333 }; return 0 ; }
constexpr修饰函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <iostream> #include <functional> using namespace std;constexpr int func () { return 0 ; } int main () { return 0 ; }
修饰模板函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <iostream> #include <functional> using namespace std;constexpr int func () { return 0 ; } struct Person { const char * name; int age; }; template <class T>constexpr T display (T t) { return t; } int main () { Person p{ "lichermionex" , 22 }; Person p1 = display <Person>(p); constexpr int ret = display <int >(22 ); constexpr Person p3{ "lichermionex" , 22 }; constexpr Person p4 = display <Person>(p3); return 0 ; }
修饰构造函数,构造函数必须是空的。只能写初始化列表里面的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> using namespace std;struct T { constexpr T (int a, int b, const char * p) :_a(a) ,_b(b) ,_p(p) { } int _a; int _b; const char * _p; }; int main () { constexpr T t (22 , 33 , "lic" ) ; return 0 ; }
constexpr关键字就是为了能够在编译期间判断常量的值,减少在运行期间的判断。提高效率。
3.2 using 基本变量和函数指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #include <iostream> using namespace std; typedef int (*func_ptr1) (int , string) ;using func_ptr2 = int (*)(int , string);int func (int a, string b) { cout << "a : " << a << " " << "b : " << b << endl; return 0 ; } int main () { typedef int t; t a = 10 ; t b = 10 ; using t2 = int ; t2 a1 = 10 ; t2 b1 = 10 ; func_ptr1 f1 = func; func_ptr2 f2 = func; f1 (1 , "lic1" ); f2 (2 , "lic2" ); (*f1)(3 , "lic3" ); (*f2)(4 , "lic4" ); return 0 ; }
**模板使用 using **
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <iostream> #include <map> using namespace std; template <class T >struct MyMap { typedef map<int , T> mapType; }; template <class T >using MMap = map<int , T>; int main () { MyMap<int >::mapType m1{ {1 ,1 }, {2 , 2 }, {3 ,3 } }; MyMap<double >::mapType m2{ {1 ,1.1 }, {2 ,2.2 }, {3 ,3.3 } }; MyMap<std::string>::mapType m3{ {1 , "one" }, {2 , "two" }, {3 , "three" } }; MMap<int > m4{ {1 ,1 }, {2 , 2 }, {3 ,3 } }; MMap<double > m5{ {1 ,1.1 }, {2 ,2.2 }, {3 ,3.3 } }; MMap<std::string> m6{ {1 , "one" }, {2 , "two" }, {3 , "three" } }; return 0 ; }
3.3 委托构造 构造函数调用构造函数。不要形成闭环。尽量写在初始化列表里面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include <iostream> using namespace std; class Test { public : Test (){} Test (int max) { _max = max > 0 ? max : 100 ; } Test (int max, int min) { _max = max > 0 ? max : 100 ; _min = min > 0 && min < max ? min : 1 ; } Test (int max, int min, int mid) { _max = max > 0 ? max : 100 ; _min = min > 0 && min < max ? min : 1 ; _mid = mid < max && mid > min ? mid : 50 ; } private : int _max; int _min; int _mid; }; class Test2 { public : Test2 () {} Test2 (int max) { _max = max > 0 ? max : 100 ; } Test2 (int max, int min) :Test2 (max) { _min = min > 0 && min < max ? min : 1 ; } Test2 (int max, int min, int mid) :Test2 (max, min) { _mid = mid < max && mid > min ? mid : 50 ; } private : int _max; int _min; int _mid; }; int main () { return 0 ; }
构造函数调用构造函数。
3.4 继承构造函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #include <iostream> #include <string> using namespace std; class Base { public : Base (int i) :_i(i) {} Base (int i, int j) :_i(i) ,_j(j) {} Base (int i, int j, int k) :_i(i) ,_j(j) ,_k(k) {} void func (int i) { cout << "func(int i)" << "i " << i << endl; } void func (int i, string str) { cout << "func(int i, string str) " << "i : " << i << "str : " << str << endl; } public : int _i; int _j; int _k; }; class Child : public Base{ public : using Base::Base; using Base::func; void func () { cout << "func()" << endl; } }; int main () { Child c{ 1 , 2 , 3 }; cout << "_i : " << c._i << endl; cout << "_j : " << c._j << endl; cout << "_k : " << c._k << endl; c.func (1 ); c.func (2 , "lic" ); c.func (); return 0 ; }
继承基类的构造函数
继承基类的隐藏函数,或者隐藏属性。
3.5 初始化列表 统一初始化 {}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <iostream> #include <string> using namespace std; class Person { public : Person (int age) :_age(age) { } Person (int age, string name) :_age(age) ,_name(name) { } private : int _age; string _name; }; int main () { Person p1 (22 ) ; Person p2 = 33 ; Person p3{ 44 }; Person p4 ={ 44 }; int a1{ 10 }; int a2={ 10 }; char ch1{ 2 }; char ch2={ 2 }; int arr1[]{ 1 ,2 ,3 }; int arr2[]={ 1 ,2 ,3 }; int * p1 = new int { 44 }; int * p2 = new int [3 ]{1 , 3 , 4 }; return 0 ; }
聚合体类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <iostream> #include <string> using namespace std; struct T1 { int x; long y; protected : int z; }; struct T2 { int x; long y; protected : static int z; }; struct T3 { int a = 4 ; int arr[3 ]{ 1 ,2 ,3 }; int c; }; int T2::z = 44 ;int main () { int x1[]{ 1 ,2 ,3 ,4 }; int x2[]={ 1 ,2 ,3 ,4 }; T2 t{ 1 ,2 }; T3 t3{ 4 , {4 ,5 ,6 }, 7 }; return 0 ; }
initializer_list
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> #include <string> #include <initializer_list> using namespace std;void func (initializer_list<int > ls) { initializer_list<int >::iterator it = ls.begin (); while (it != ls.end ()) { cout << *it << " " ; ++it; } cout << endl; } void func (initializer_list<char >& ls) { initializer_list<char >::iterator it = ls.begin (); while (it != ls.end ()) { cout << *it << " " ; ++it; } cout << endl; } int main () { func ({ 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }); func ({ 'a' , 'b' , 'c' , 'd' , 'e' }); return 0 ; }
3.7 可调用对象 类似函数指针一样,直接对象,然后就是需要的参数。
3.7.1 可调用对象 1.函数指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> #include <string> using namespace std; void print (int num, const string& name) { cout << "num : " << num << " : " << "name : " << name << endl; } using funcptr = void (*)(int , const string&); int main () { funcptr p = print; p (10 , "lichermionex" ); return 0 ; }
2.仿函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <iostream> #include <string> using namespace std; class Test { public : void operator () (const string& msg) { cout << "msg : " << msg << endl; } }; int main () { Test t; t ("lichermionex" ); return 0 ; }
3将类对象转换为函数指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <iostream> #include <string> using namespace std; using funcptr = void (*)(int , const string&); class Test { public : operator funcptr () { return world; } static void world (int a, const string& s) { cout << "a:" << a << endl; cout << "s:" << s << endl; } }; int main () { Test tt; tt (18 , "lichermionex" ); return 0 ; }
4.类的函数指针或者类成员的指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <iostream> #include <string> using namespace std; using funcptr = void (*)(int , const string&); class Test { public : void hello (int a, const string& s) { cout << "a:" << a << endl; cout << "s:" << s << endl; } static void world (int a, const string& s) { cout << "a:" << a << endl; cout << "s:" << s << endl; } int _id; }; int main () { funcptr f = Test::world; using fptr = void (Test::*)(int , const string&); fptr f1 = &Test::hello; Test ttt; (ttt.*f1)(22 , "licher" ); using ptr1 = int Test::*; ptr1 pt = &Test::_id; ttt.*pt = 555 ; return 0 ; }
总结
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #include <iostream> #include <string> using namespace std;using funcPtr = void (*)(int , const string&);using funcPtr1 = void (*)(int );void print (int id, const string& str) { cout << "id : " << id << " " << "str : " << str << endl; } class test { public : void operator () (int id, const string& str) { cout << "id : " << id << " " << "str : " << str << endl; } static void hello (int id, const string& str) { cout << "id : " << id << " " << "str : " << str << endl; } void world (int id, const string& str) { cout << "id : " << id << " " << "str : " << str << endl; } static void print_int (int x) { cout << "print x : " << x << endl; } operator funcPtr1 () { return print_int; } }; int main () { funcPtr ptr1 = print; print (1 , "lic1" ); test t; t (2 , "lic2" ); funcPtr ptr2 = test::hello; ptr2 (3 , "lic3" ); test ttt; using fptr = void (test::*)(int , const string&); fptr ptr3 = &test::world; (ttt.*ptr3)(4 , "lic4" ); ttt (555 ); return 0 ; }
3.7.2函数包装器 std::function<返回值(参数列表)> diy_name = 可调用对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #include <iostream> #include <string> #include <functional> using namespace std; void print (int num, const string& name) { cout << "num : " << num << " : " << "name : " << name << endl; } using funcptr = void (*)(int , const string&); class Test { public : void operator () (const string& msg) { cout << "msg : " << msg << endl; } operator funcptr () { return world; } void hello (int a, const string& s) { cout << "a:" << a << endl; cout << "s:" << s << endl; } static void world (int a, const string& s) { cout << "a:" << a << endl; cout << "s:" << s << endl; } int _id; }; int main () { function<void (int , const string&)> f1 = print; print (1 , "lic1" ); function<void (int , const string&)> f2 = Test::world; f2 (2 , "lic2" ); Test t1; function<void (const string&)> f3 = t1; f3 ("lic333" ); Test t2; function<void (int , const string&)> f4 = t2; f4 (4 , "lic4444" ); return 0 ; }
基本演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include <iostream> #include <string> #include <functional> using namespace std; class A { public : A (const function<void (int , string)>& callback) :_callback(callback) { } void notify (int id, string name) { _callback(id, name); } private : function<void (int , string)> _callback; }; void print (int id, string name) { cout << "id : " << id << endl; cout << "string : " << name << endl; } using funcptr = void (*)(int , const string&); class Test { public : static void world (int a, const string& s) { cout << "a:" << a << endl; cout << "s:" << s << endl; } operator funcptr () { return world; } int _id; }; int main () { A a (print) ; a.notify (11 , "lic11" ); A b (Test::world) ; b.notify (22 , "lic22" ); Test tb; function<void (int , const string&)> f4 = tb; A c (tb) ; c.notify (3 , "lic33" ); return 0 ; }
3.7.3 绑定器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> #include <string> #include <functional> using namespace std; void output (int x, int y) { cout << "x : " << x << endl; cout << "y : " << y << endl; } int main () { bind (output, 1 , 2 )(); bind (output, placeholders::_1, 2 )(1111 ); bind (output, 2 , placeholders::_1)(1111 ); bind (output, 2 , placeholders::_2)(10 , 10 ); bind (output, placeholders::_1, placeholders::_2)(10 , 11 ); bind (output, placeholders::_2, placeholders::_1)(10 , 11 ); return 0 ; }
直接结果
1 2 3 4 5 6 7 8 9 10 11 12 x : 1 y : 2 x : 1111 y : 2 x : 2 y : 1111 x : 2 y : 10 x : 10 y : 11 x : 11 y : 10
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <iostream> #include <string> #include <functional> using namespace std; void testFunc (int x, int y, const function<void (int , int )> & f) { if (x % 2 == 0 ) { f (x, y); } } void output (int x, int y) { cout << "x : " << x << " " << "y : " << y << " " << "x + y : " << (x + y) << endl; } int main () { for (int i = 0 ; i < 10 ; ++i) { auto f1 = bind (output, i + 100 , i + 200 ); testFunc (i, i, f1); auto f2 = bind (output, placeholders::_1, placeholders::_2); testFunc (i, i, f2); } return 0 ; }
绑定类的成员函数和成员属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <iostream> #include <string> #include <functional> using namespace std; class Test { public : void output (int x, int y) { cout << "x : " << x << " y : " << y << endl; } int _number = 100 ; }; int main () { Test t; bind (&Test::output, &t, 1 , 2 )(); bind (&Test::output, &t, 1 , placeholders::_2)(777 ,888 ); auto f = bind (&Test::_number, &t); f () = 777 ; cout << f () << endl; return 0 ; }
类的属性和方法属于实例化的对象,需要创建实例化的对象后 在继续进行绑定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <iostream> #include <string> #include <functional> using namespace std; class Test { public : void output (int x, int y) { cout << "x : " << x << " y : " << y << endl; } int _number = 100 ; }; int main () { Test t; bind (&Test::output, &t, 1 , 2 )(); bind (&Test::output, &t, 1 , placeholders::_2)(777 ,888 ); auto f = bind (&Test::_number, &t); cout << f () << endl; f () = 777 ; cout << f () << endl; function<void (int , int )> ff = bind (&Test::output, &t, 520 , placeholders::_2); ff (0 , 1314 ); function<int &(void )> fff = bind (&Test::_number, &t); return 0 ; }
3.8 右值引用 左值:loactor value。可以定位的值
右值:read value。只读值
左值:空间
右值:数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <iostream> int main () { int a = 44 ; int & refa = a; 44 ; 'a' ; "abcd" ; int && c = 44 ; const int & d = a; const int & d2 = c; const int & d3 = 44 ; const int && f = 44 ; return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 #include <iostream> using namespace std;class test { public : test () :_a(new int { 22 }) { cout << "test()" << endl; cout << &_a << endl; } test (const test& t) :_a(new int { *t._a }) { cout << &_a << endl; cout << "test(const test& t)" << endl; } test (test&& t) :_a(t._a) { t._a = nullptr ; cout << " test(test&& t)" << endl; cout << &_a << endl; } ~test () { cout << "~test()" << endl; delete _a; } public : int * _a; }; test getobj () { test t; return t; } int main () { test t = getobj (); test&& t1 = getobj (); return 0 ; }
主要是延长将亡值的声明周期,实现浅拷贝。
&& 的特性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include <iostream> #include <string> using namespace std;template <class T>void f (T&& param) ; template <class T>void f1 (const T&& param) ; int main () { f (10 ); int x = 10 ; f (x); f1 (55 ); return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <iostream> #include <string> using namespace std;int main () { int x = 1 ; int y = 2 ; auto && v1 = x; auto && v2 = 222 ; int && a1 = 44 ; auto && bb = a1; auto && cc = 66 ; int a2 = 5 ; int & a3 = a2; auto && ccc = a3; auto && ccc1 = a2; const int & s1 = 1000 ; const int && s2 = 1000 ; auto && dd = s1; auto && ee = s2; const auto && xxx = 5 ; return 0 ; }
通过右值推导 T&& 或者 auto&& 得到的是一个右值引用类型。 右值是具体的右值,不是变量。
const T&& 就是一个右值类型,不需要推导了的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> using namespace std;void print (int & i) { cout << "left : " << i << endl; } void print (int && i) { cout << "right : " << i << endl; } void forward (int && k) { print (k); } int main () { int i = 55 ; print (i); print (44 ); forward(444 ); return 0 ; }
move
1 2 3 4 5 6 7 8 9 10 11 12 13 #include <iostream> #include <list> #include <string> using namespace std;int main () { list<string> ls{ {"lic1" }, {"lic2" }, {"lic3" } }; list<string> ls2 = move (ls); return 0 ; }
完美转发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <iostream> #include <list> #include <string> using namespace std;template <class T>void print (T& t) { cout << "left value : " << t << endl; } template <class T>void print (T&& t) { cout << "right value : " << t << endl; } template <class T>void testforward (T&& v) { print (v); print (move (v)); print (forward<T>(v)); } int main () { testforward <int >(520 ); int num = 44 ; testforward (num); return 0 ; }