C++ 14

1 二进制字面量

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>
using namespace std;

int main()
{
// 字面量:右值。
123;
12.4f;
134.56;
'c';
"lichermionex";
false;
true;
nullptr;
NULL;
0b1100;

// 二进制字面量:零B 零b
int num1 = 0B1010; // 8421
int num2 = 0b1010; // 8421
int num3 = 0b11010; // 16 8421
cout << num1 << endl;
cout << num2 << endl;
cout << num3 << endl;

auto x1 = 0b10u;
auto x2 = 0b10ul;
auto x3 = 0b10ull;

cout << "x1 : " << typeid(x1).name() << endl;
cout << "x2 : " << typeid(x2).name() << endl;
cout << "x3 : " << typeid(x3).name() << endl;

int y1 = 0b111'1111; // 不能够最后面和0b后面,也不能够连续。
int y2 = 0xff'ff;
int y3 = 077'77;
int y4 = 11'111'111;

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
#include <iostream>
using namespace std;

enum Permission
{
Read = 0b001,
Write = 0b010,
Execute = 0b100,
};

int main()
{
// 权限检查
int user1 = 0b111;
int user2 = 0b101;
int user3 = 0b001;

if (user2 & Permission::Read)
{
cout << "user2:有读权限" << endl;
}

if (user2 & Permission::Write)
{
cout << "user2:有写权限" << endl;
}

if (user2 & Permission::Execute)
{
cout << "user2:有执行权限" << 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
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <iomanip>
using namespace std;

struct Color
{
static constexpr unsigned int ALPHA_MASK = 0b1111'1111'0000'0000'0000'0000'0000'0000;
static constexpr unsigned int RED_MASK = 0b0000'0000'1111'1111'0000'0000'0000'0000;
static constexpr unsigned int GREEN_MASK = 0b0000'0000'0000'0000'1111'1111'0000'0000;
static constexpr unsigned int BLUE_MASK = 0b0000'0000'0000'0000'0000'0000'1111'1111;

Color(unsigned char a, unsigned char r, unsigned char g, unsigned char b)
{
argb = (a << 24) | (r << 16) | (g << 8) | b;
}

unsigned char getAlpha() const
{
return argb >> 24;
}

unsigned char getRed() const
{
return static_cast<unsigned char>((argb & RED_MASK) >> 16);
}

unsigned char getGreen() const
{
return static_cast<unsigned char>((argb & GREEN_MASK) >> 8);
}

unsigned char geBlue() const
{
return static_cast<unsigned char>(argb & BLUE_MASK);
}

void print() const
{
cout << "ARGB: 0x"
<< hex
<< setfill('0')
<< setw(8)
<< argb
<< endl;
}
unsigned int argb;
};

int main()
{
Color c(125,200,100,255);
c.print();

cout << (int)c.getAlpha() << endl;
cout << (int)c.getRed() << endl;
cout << (int)c.getGreen() << endl;
cout << (int)c.geBlue() << endl;

return 0;
}

2 自定义字面量

单一类型

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
69
70
71
72
#include <iostream>
#include <string>
using namespace std;

// 1.整型类型:unsigned long long
// 2.浮点类型:long double
// 3.字符类型:char
// 4.字符串类型:const char*, size_t;
/*
返回值 operator"" _xxx(){}
*/

// 50000 = 5_wan
constexpr unsigned long long operator"" _wan(unsigned long long value)
{
return value * 10000;
}

// 1km=1000;
constexpr long double operator"" _km(long double value)
{
return value * 1000.0L;
}

constexpr char operator"" _upper(char c)
{
if (c >= 'a' && c <= 'z')
{
return c - 'a' + 'A';
}

return c;
}

// 字符串添加括号
string operator"" _ins(const char* str, size_t size)
{
return string( "(") +str + ")";
}

// 重复添加
string operator"" _repeat(const char* str, size_t size)
{
string result;
for (int i = 0; i < 3; ++i)
{
result += str;
}

return result;
}

int main()
{
// 自定义字面量
unsigned long long dist = 5_wan;
cout << "dist:" << dist << endl;

long double dist2 = 3.5_km;
cout << "dist2:" << dist2 << endl;

char ch = 'a'_upper;
cout << "ch:" << ch << endl;

string str1 = "lic"_ins;
string str2 = "lic"_repeat;

cout << "str1:" << str1 << endl;
cout << "str2:" << str2 << 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>
using namespace std;

// 1.整型类型:unsigned long long
// 2.浮点类型:long double
// 3.字符类型:char
// 4.字符串类型:const char*, size_t;
/*
返回值 operator"" _xxx(){}
*/

struct color
{
uint8_t r, g, b;

void print()
{
cout << "r:" << (int)r << endl;
cout << "g:" << (int)g << endl;
cout << "b:" << (int)b << endl;
}
};

color operator"" _rgb(const char* str, size_t size)
{
int r, g, b;
sscanf(str, "%d,%d,%d", &r, &g, &b);
return color{ (uint8_t)r,(uint8_t)g,(uint8_t)b };
}

color operator"" _rgb2(unsigned long long value)
{
int r, g, b;
return color{ (uint8_t)((value >> 16) & 0xFF),(uint8_t)((value >> 8) & 0xFF),(uint8_t)(value & 0xFF) };
}

int main()
{
color c1 = "255,100,100"_rgb;
c1.print();

color c2 = 0xff6699_rgb2;
c2.print();

return 0;
}

C++ 14的改进

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
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <complex>

//using namespace std::chrono_literals;
//using namespace std::string_literals;
//using namespace std::complex_literals;

using namespace std;
using namespace chrono;

// 1.整型类型:unsigned long long
// 2.浮点类型:long double
// 3.字符类型:char
// 4.字符串类型:const char*, size_t;
/*
返回值 operator"" _xxx(){}
*/

// 1. ++14 字符串类型的字面量 忽略字符串的长度
chrono::seconds operator"" _s(const char* value)
{
return chrono::seconds(stoi(value));
}

int main()
{
// 标准库的内置字面量
// 1.时间字面量;6个。
auto sec = 10s; // c++内置的没有_。 s
auto ms = 10ms;
auto us = 10us;
auto ns = 10ns;
auto min = 10min;
auto h = 10h;

chrono::seconds total = 1h + 30min + 600s;
cout << total.count() << endl;

//this_thread::sleep_for(5_s); // 自定义的
//cout << "---" << endl;
//this_thread::sleep_for(5s); // 标准库的

// 2.字符串类型字面量
auto s1 = "hello world"s; // string 1
auto s2 = u"hello world"s; // u16string 2
auto s3 = U"hello world"s; // u32string 4
auto s4 = L"hello world"s; // wstring win2 linux4

string name = "lic"s + "her"s + "mi"s + "one"s + "x"s; // 编译期间完成的。
cout << name << endl;

// 3.复数字面量
auto comp1 = 1.0 + 2i;
auto comp2 = 3i;
auto comp3 = 3if;
auto comp4 = 3il;

return 0;
}

3 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
33
34
35
36
37
#include <iostream>
#include <string>
#include <thread>
#include <complex>
using namespace std;

// 修饰函数或者常量:计算转移到编译时,优化性能,类型安全,支持泛型。
// const
// constexpr

int getInput()
{
int input;
cin >> input;
return input;
}

void test()
{
// 1.初始化时期
// const编译或者运行。
const int number = 123; // 编译期间的。
const int number2 = getInput(); // 运行期间的
const int* ptr = new int{ 333 }; // 运行期间的
int* const ptr1 = new int{ 444 }; // 运行期间的
*ptr1 = 8888;

// constexpr一定是编译时初始化
constexpr int size = 1000;
//constexpr int len = getInput(); error

}

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
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <iostream>
#include <string>
#include <thread>
#include <complex>
using namespace std;

// 修饰函数或者常量:计算转移到编译时,优化性能,类型安全,支持泛型。
// const
// constexpr

int getInput()
{
int input;
cin >> input;
return input;
}

void test()
{
// 1.初始化时期
// const编译或者运行。
const int number = 123; // 编译期间的。
const int number2 = getInput(); // 运行期间的
const int* ptr = new int{ 333 }; // 运行期间的
int* const ptr1 = new int{ 444 }; // 运行期间的
*ptr1 = 8888;

// constexpr一定是编译时初始化
constexpr int size = 1000;
//constexpr int len = getInput(); error

// 例子定义数组
int arr[size] = { 0 };
int arr1[number] = { 0 };

// 目标的非类型参数
}

template<class T, int size>
class Fixarray
{
public:
int getLen()const
{
return size;
}

Fixarray() = default;

Fixarray(int size)
{
arr = new T[size];
}

private:
T* arr;
};

// 指定存储的bit位数
constexpr int wild = 4;
struct BitField
{
unsigned int x : wild;
unsigned int y : 2;
};

// 内存对齐
struct alignas(8) stu
{
int id; // 0-3
char name[6]; // 4-10
double score; // 16-24
char sex; // 25
};

int main()
{
constexpr int size = 14;
// 1.数组
int arr[size] = { 0 };

// 2.模板的非类型参数
Fixarray<int, size> fx(14);

cout << fx.getLen() << endl;
// 3.case的判断条件
int input = getInput();
constexpr int stop = 0;
constexpr int start = 1;
switch (input)
{
case stop:
cout << "程序终止。。。" << endl;
break;
case start:
cout << "程序开始。。。" << endl;
break;
default:
break;
}

// 4.位域
BitField b1;
b1.x = 15;
cout << b1.x << endl;
b1.x = 16;
cout << b1.x << endl; // 被截断了的

cout << sizeof(stu) << endl;
alignas(double) char buffer[12];
cout << sizeof(buffer) << endl;

return 0;
}

C++ 14修改

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
69
70
71
72
73
74
75
76
77
#include <iostream>
using namespace std;
// c++11 只能有一条return
// c++14
/*
C++11 中,
1.被constexpr修饰的函数返回值不允许为 void
2.被constexpr修饰的构造函数必须为空,只能通过初始化列表初始化所有成员(初始化需放到初始化列表)
3.被constexpr修饰的类成员函数会隐式成为const 函数
C++14中,
1.被constexpr修饰的函数允许返回值为 void
2.被constexpr修饰的构造函数可以有函数体,可以包含控制流语句(初始化需放到初始化列表)
3.被constexpr修饰的类成员函数体内部可以修改类成员的值。
*/

constexpr int fact(int n)
{
int result = 1;
for (int i = 1; i <= n; ++i)
result *= i;
return result;
}

class point
{
public:
constexpr point(int x, int y)
: _x(x), _y(y)
{
if (_x > 100 || _y > 100)
{
_x = _y = 100; // 改成员,不是形参
}
}

constexpr void setx(int v) { _x = v; }
constexpr void sety(int v) { _y = v; } // 去掉 const,加 constexpr

constexpr int getx() const { return _x; }
constexpr int gety() const { return _y; }

// 注意:validate 非 const,只能对非 const 对象调用
constexpr void validate()
{
if (_x * _y > 10000)
{
_x = 100;
_y = 200;
}
}

private:
int _y;
int _x;
};

constexpr point movepoint(point p, int x, int y)
{
p.setx(p.getx() + x);
p.sety(p.gety() + y);
return p;
}

int main()
{
// cout << fact(10) << endl;

constexpr point p1(100, 200); // _y=200>100 → 截断为 100
point p2{ 1, 4 };
constexpr point p3 = p1;
constexpr point p4 = movepoint(p1, 2, 3);

// p1.validate(); // 错误:p1 是 const 对象,validate 非 const
p2.validate(); // OK

return 0;
}

4 lambda

4.1 泛型lambda

C++14 匿名函数的参数可以是可调用对象。 注意函数体里面实现的功能是可调用对象支持的功能。

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 <vector>
#include <list>
#include <string>
#include <array>
#include <algorithm>
using namespace std;

// 泛型lambda->允许在参数中使用

void lambda1()
{
// c++11
auto num = 1;
auto ch = 'a';
auto sum = [](int x, int y)->int
{
return x + y;
};

// c++14 1.匿名函数的参数可以是:可调用对象的。
auto add = [](auto para1, auto para2) // 返回的是一个可调用对象,这里只是定义。
{
return para1 + para2;
};

cout << add(1, 2) << endl;
cout << add(3.5, 4.6) << endl;
cout << add("hello "s, "world"s) << endl;

// 2.比较两个变量相等
auto compare = [](auto p1, auto p2)
{
return p1 == p2;
};

cout << compare(1, 2) << endl;
cout << compare("hello"s, "world"s) << endl;
cout << compare("hello"s, "hello"s) << endl;
cout << compare(1.2, 2.2) << endl;

// 3.
// 容器封装--》序列容器 封装find方法
// vector array deque list forward_list.
auto containerFind = [](const auto& c1, const auto& value)
{
auto it = std::find(c1.begin(), c1.end(), value);
return it != c1.end();
};

vector<int> nums{ 1,3,4,5,6,8 };
list<string> ls{ "lic", "her", "mi", "one" };
array<int, 6> arr1{ 1,3,4,5,6,7 };

cout << containerFind(nums, 10) << endl;
cout << containerFind(ls, "her") << endl;
cout << containerFind(arr1, 7) << endl;
}

int main()
{
lambda1();
return 0;
}

进阶1

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
69
70
71
72
73
74
#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <array>
#include <algorithm>
using namespace std;

// 1.排序-->降序
auto descending = [](const auto& p1, const auto& p2)
{
return p1 > p2;
};

// 2.根据对象的年龄属性
auto descending2 = [](const auto& p1, const auto& p2)
{
return p1.age > p2.age;
};

// 3.根据对象的任意属性
auto descending3 = [](const auto memberPtr)
{
return [memberPtr](const auto& p1, const auto& p2)
{
return p1.*memberPtr > p2.*memberPtr;
};
};

auto print = [](const auto& p)
{
for (const auto& e : p)
{
cout << e << " ";
}
cout << endl;
};

struct people
{
string name;
int age;
};

void mysort()
{
vector<int> nums{ 1,3,4,5,6,8 };
vector<string> ls{ "lic", "her", "mi", "one" };

sort(nums.begin(), nums.end(), descending);
sort(ls.begin(), ls.end(), descending);
print(nums);
print(ls);

vector<people> peoples{ {"lic", 12}, {"ice",13}, {"emma",14} };
for (const auto& each : peoples)
cout << each.age;
cout << endl;
sort(peoples.begin(), peoples.end(), descending2);
for (const auto& each : peoples)
cout << each.age;
cout << endl;

sort(peoples.begin(), peoples.end(), descending3(&people::age));
for (const auto& each : peoples)
cout << each.age;
cout << endl;
}

int main()
{
mysort();
return 0;
}

进阶2

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
#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <array>
#include <algorithm>
using namespace std;

// 泛型函数组合器,高阶函数,
// 1.接收函数作为参数(泛型lambda)。 函数组合---实现新的功能,类型安全的。decltype.

void mycompose()
{
auto increment = [](auto x)
{
return x + 1;
};

auto squre = [](auto x)
{
return x * x;
};

auto toString = [](auto x)
{
return to_string(x);
};

// 组合器函数---传递两个函数作为参数。 f(g(x))
auto compose = [](auto x, auto y)
{
return [x,y](auto value)
{
return x(y(value));
};
};

// 1.先增长,求平方。
auto incrementThesqure = compose(squre, increment);
// 2.平方,字符串
auto squreTosting = compose(toString, squre);

cout << incrementThesqure(9) << endl;
cout << squreTosting(9) << endl;
}

int main()
{
mycompose();

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
#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <array>
#include <algorithm>
using namespace std;

// 泛型函数组合器,高阶函数,
// 1.接收函数作为参数(泛型lambda)。 函数组合---实现新的功能,类型安全的。decltype.

void mycompose()
{
int number = 10;
auto func = [number](int x, int y) // mutable 可以修改按值捕获的
{
return x + y + number;
};

class xxxlambda
{
public:
xxxlambda(int value):number(value){}

//仿函数
auto operator()(int x, int y) const // const等价按值捕获。
{
return x + y + number;
}
private:
int number;
};
}

int main()
{
mycompose();

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
#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <array>
#include <algorithm>
#include <cmath>
using namespace std;

// 泛型函数组合器,高阶函数,
// 1.接收函数作为参数(泛型lambda)。 函数组合---实现新的功能,类型安全的。decltype.

void lambda()
{
// 简单变量捕获
int number = 100;
auto lambda = [y = number](int x, int z) // 对象里面多一个变量 y
{
cout << "y:" << y << endl;
return y;
};

cout << "lambda:" << lambda(number, 1) << endl;

// 复杂对象的捕获
string name{ "lichermidd" };
vector<string> words{ {"lic22"}, {"lic33"} };

auto lambda2 = [x = name, y = words]() // 按值进行捕获,拷贝了一份到对象里面。
{
cout << x << endl;
cout << y.size() << endl;
cout << y[1] << endl;
};
name = "xxxxxx";
words.push_back("ice");

lambda2();

// 捕获函数的返回值。
int base = 2;
int ex = 5;
auto lam = [res = static_cast<int>(std::pow(2, 5))]()
{
cout << "res" << res << endl;
};
lam();
}

int main()
{
lambda();

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
#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <array>
#include <algorithm>
#include <cmath>
using namespace std;

void lambda()
{
int number = 100;
auto lam1 = [&number]()
{
number++;
cout << "number:" << number << endl;
return number;
};
cout << lam1() << endl;

auto lam2 = [&y = number]
{
y++;
cout << "number:" << y << endl;
return y;
};
cout << lam2() << endl;

cout << "----" << number << endl;

// ref进行初始胡捕获,引用包装器
auto lam3 = [y = ref(number)]()
{
//y++; // 强制类型转换 y是一个对象。

y.get() = 99;
return y.get();
};
lam3();
cout << "----" << number << endl;

// 常量引用,强制类型转换
auto lam4 = [&y = static_cast<const int&>(number)]()
{
cout << "y:" << y << endl;
};

// 常量引用,包装器
auto lam5 = [y = cref(number)]()
{
cout << "y:" << y << endl;
};

}

int main()
{
lambda();

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>
#include <vector>
#include <list>
#include <string>
#include <array>
#include <algorithm>
#include <cmath>
#include <memory>
using namespace std;

void lambda()
{
// 移动捕获
vector<int> v{ 1,3,4,5,6,7,7 };
// 将左值进行了类型转换--》右值引用。
move(v);

auto num1 = move(v); // 移动构造。右值,选择移动构造。

cout << v.size() << endl;

// c++14初始化捕获。
auto lambda1 = [vec = move(num1)]() mutable
{
cout << vec.size() << endl;
vec.push_back(100);

return vec;
};

auto ret = lambda1();
for (auto e : ret)
{
cout << e << " ";
}
cout << endl;

// 独占智能指针
unique_ptr<int> ptr1{ new int{222} };

auto lambda2 = [ptr = move(ptr1)]()
{
cout << *ptr.get() << endl;
*ptr = 55;
cout << "new value:" << *ptr << endl;
};
cout << "ptr1 " << (ptr1 ? "not null" : "null \n");
lambda2();
}

int main()
{
lambda();

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
#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <type_traits>
using namespace std;

// 捕获列表根据 左右值区分。
// 定义模板函数

template<class T>
auto increment(T&& value)
{
// T类型的是左值引用 value左值。
// T类型的不是左值引用 value右值。
return [cap = forward<T>(value)]() mutable
{
cout << "T 的类型:";
if (is_same<T, string>::value)
{
cout << "string" << endl;
}
else if(is_same < T, string&>::value)
{
cout << "string&" << endl;
}
else if (is_same < T, string&&>::value)
{
cout << "string&&" << endl;
}

cout << "value的类型";
if (is_lvalue_reference<decltype(value)>::value)
{
cout << "左值引用" << endl;
}
else if(is_rvalue_reference<decltype(value)>::value)
{
cout << "右值引用" << endl;
}

cout << cap << endl;
};
};

void lambda()
{
string str{ "hello world" };
auto ret1 = increment(str);
auto ret2 = increment(string("lic"));
auto ret3 = increment(move(str));

ret1();
ret1();
ret1();

}

int main()
{
lambda();

return 0;
}

5 auto 和 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
49
50
51
52
53
54
55
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

// c11
auto func() -> int
{
return 0;
}

// c14 多个return, 保证返回的类型必须一样的
auto func2(int x, double y) ->double
{
if (x / 2)
{
return x + y;
}
else
{
return 1.0;
}
}

// 可以用在递归函数
auto fact(int x)
{
if (x == 1)
{
return 1;
}

return x * fact(x - 1);
}

// 剥离引用 cv限定。
// const + 指针 保留
int& getRef()
{
static int x = 999;
return x;
}

auto fun1() { return getRef(); }
auto& fun2() { return getRef(); }
auto fun3() { const int x = 10; return x; }
auto fun4() { const char* name = "lic"; return name; }

int main()
{
func2(1, 1.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
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

//c++11 返回值类型后置 + 模板函数中
//auto->会剥离引用,c / v
//decltype->保留引用,保留c / v

template<class T, class U>
auto func1(T& t, U& u) -> decltype(t + u) // c++11的返回值类型后置。
{
return t + u;
}

template<class T, class U>
decltype(auto) func2(T& t, U& u)
{
return t + u;
}

string& getname()
{
static string name = "lic";
return name;
}

auto name1 = getname();
decltype(auto) name2 = getname();

decltype(auto) getele(vector<int>& vec, size_t index)
{
return vec[index];
}

int main()
{
string s1{ "hello " };
const string s2{ "world" };
auto ret1 = func1(s1, s2);
auto ret2 = func2(s1, s2);



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
#include <iostream>
#include <vector>
#include <string>
using namespace std;


int main()
{
int x = 10;
int& y = x;
const int z = 100;
volatile int d = 77;
int&& n = 55; // n 是 int&& 左值(有名字的右值引用,本身是左值)

// ========== decltype:完全保留原类型(含引用、const、volatile) ==========
decltype(x) x1 = 100; // int (x 是 int)
decltype(y) y1 = x1; // int& (y 是 int&,引用被保留)
decltype(z) z1 = x1; // const int (z 是 const int,const 被保留)
decltype(d) d1 = x1; // volatile int (d 是 volatile int,volatile 被保留)
decltype(n) n1 = 22; // int&& (n 是 int&&,右值引用被保留)

// ========== auto:值拷贝,丢弃引用和顶层 const/volatile ==========
auto x2 = x; // int (普通拷贝)
auto y2 = y; // int (引用被丢弃,拷贝值)
auto z2 = z; // int (顶层 const 被丢弃)
auto d2 = d; // int (顶层 volatile 被丢弃)
auto n2 = n; // int (右值引用被丢弃,n 本身是左值,拷贝其值)

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
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int x = 22;
decltype(auto) test1()
{
return x;
}

decltype(auto) test2()
{
return (x);
}

int m = 3;
int n = 3;
decltype(auto) test2()
{
return (m + n); // 算出来6, int
}

int main()
{
int x = 10;
decltype(auto) v1 = x;
decltype(auto) v2 = (x);

return 0;
}

6 聚合类

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
#include <iostream>
#include <vector>
#include <string>
using namespace std;

// 聚类类:数据的集合。讲的是成员的初始化。
// 1.构造,拷贝构造,析构函数,拷贝运算符重载,移动运算符重载。
// 2.非静态数据成员,权限public
// 3.非静态数据成员,不能有默认的初始化器 = {}
// 4.没有虚函数,
// 5.没有虚基类,更正:C++14中聚合类不允许有基类
// 数据的集合。

// 1.使用{}初始化内部的 public成员。
// 2.初始化和声明的顺序一致。
// 3.只初始化一部分,剩下的默认初始化。只能给剩下尾部的不初始化。
// 4.支持嵌套的

class test
{
public:
// 声明 + 定义
int x;
string name;
vector<int> v; // 聚合体可以嵌套的
int arr[10];

static int bb; // 声明
private:
static int zz; // 声明
};

int test::bb = 44; // 定义
int test::zz = 44; // 定义

class example
{
public:
int a;
int b;
example() = default;
example(const example&) = default;
example(example&&) = default;

example& operator=(const example&) = default;
example& operator=(example&&) = default;

~example() = default;
};

int main()
{
int arr[]{ 1,2,4,5,6,7,8 }; // 数组
test t{};
test t1{ 22 };
test t2{ 22, "lichermionex" };
test t3{ 22, "lichermionex", {1,2,3,4,5,6,7} };
test t3{ 22, "lichermionex", {1,2,3,4,5,6,7} ,{11,33} };

//example e{};
//example e1{2};
//example e2{2,3};

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 <vector>
#include <string>
using namespace std;

class test
{
public:
// 1.用户自定义的默认函数
int x;
test() {} // 自定义的构造函数
test(int value):x(value){ } // 自定义的构造函数
test(const test& t) { x = t.x; }
test(test&& t) { x = t.x; }

test& operator=(const test& t)
{
x = t.x;
return *this;
}

test& operator=(test&& t)
{
x = t.x;
return *this;
}

~test(){}
};

struct tt
{
int x{ 22 }; // c11不写 c14可以
int y = 44; // c11不写 c14可以
};

int main()
{
// 1.自定义的默认函数。
// 2.私有的非静态属性。
// 3.不能够初始化-数据成员 c++14可以的。
// 4.不能够用有虚函数。
// 5.不能够有虚基类。
// 6.不是public继承。
// 7.不是基类不是聚合力

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
#include <iostream>
#include <vector>
#include <string>
using namespace std;

//C++14 对聚合类的一个重要改进是:允许在聚合类的 非静态数据成员 声明时 直接提供 默认成员初始化器{} =
class test
{
public:
int a = 2;
int b{ 3 };
int c = { 44 };
double d{ 44.4 };
const char* str{ "lichermionex" };
};

void print(const test& t)
{
cout << t.a << " ";
cout << t.b << " ";
cout << t.c << " ";
cout << t.d << " ";
cout << t.str << " ";
cout << endl;
}

int main()
{
// 不用默认初始化,就是用自己的。
test t;
test t22{}; // 等价t
test t1{ 1 };
test t2{ 1 ,2 };
test t3{ 1 ,2,3 };
test t4{ 1 ,2,3,88.7 };
test t5{ 1 ,2,3,88.7, "lic"};
print(t);
print(t1);
print(t2);
print(t3);
print(t4);
print(t5);

// 为什么需要聚合类
// 1.兼容c语言,c语言使用结构体 用{}初始化。
// 2.内存开销,没有构造函数,内存布局确定。
// 3.语法简洁。
// 4.编译期安全。未初始化的问题。

return 0;
}

7变量模板

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
69
#include <iostream>
#include <vector>
#include <limits>
#include <string>
using namespace std;

// 类模板,函数模板。
// 简单的变量模板->常量,更强大,更灵活
template<typename T>
//constexpr T pi = T(3.14L); c语言的强制类型转换
constexpr T pi = static_cast<T>(3.13L); // c++的类型转换

// 指定默认的模板参数
template<typename T = double>
constexpr T pai = T(3.233L);

// 静态方法获取值
template<typename T>
constexpr T max_value = std::numeric_limits<T>::max();

template<typename T>
constexpr T mix_value = std::numeric_limits<T>::min();

void test()
{
// 使用
constexpr double d = pi<int>;
int i = pi<int>;

cout << "d:" << d << endl;
cout << "i:" << i << endl;

cout << pai<> << endl;
cout << pai<int> << endl;

cout << "int max:" << max_value<int> << endl;
cout << "int min:" << mix_value<int> << endl;
cout << "float max:" << max_value<float> << endl;
cout << "float min:" << mix_value<float> << endl;
}

// c98/c11的特化类
template<typename T>
struct spec;

template<>
struct spec<float>
{
static constexpr float value = 3.145666f;
};

template<>
struct spec<double>
{
static constexpr double value = 3.145666L;
};

void test2()
{
float f = spec<float>::value;
double d = spec<double>::value;
}

int main()
{
test();

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
#include <iostream>
#include <vector>
#include <limits>
#include <string>
using namespace std;

// 变量模板的特化
// 全特化 显示特化
// 偏特化,偏特化

// template<> 不需要指定类型

// 1.柱模板
template<class T>
constexpr size_t typesize = sizeof(T);

// 2.全特化
template<>
constexpr size_t typesize<int> = 4;

template<>
constexpr size_t typesize<double> = 8;

template<>
constexpr size_t typesize<vector<int>> = 100; // 随便指定的

int main()
{
// 返回固定类型
size_t s1 = typesize<char>;
size_t s2 = typesize<short>;
size_t s3 = typesize<int>;
size_t s4 = typesize<double>;
size_t s5 = typesize<vector<int>>;

cout << "s1:" << s1 << endl;
cout << "s2:" << s2 << endl;
cout << "s3:" << s3 << endl;
cout << "s4:" << s4 << endl;
cout << "s5:" << s5 << 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
#include <iostream>
#include <vector>
#include <limits>
#include <string>
using namespace std;

// 变量模板的特化
// 全特化 显示特化
// 偏特化,偏特化

// 返回的类型依赖模板参数的类型

template<class T, T value>
constexpr T meter_to_feet = T(3.2808) * value;

template<class T, T value>
constexpr T feet_to_meter = T(0.3084) * value;

// c++20以前,非类型只能是整形
template<>
constexpr int meter_to_feet<int, 1> = 3;

template<>
constexpr int meter_to_feet<int, 5> = 15;

template<>
constexpr int meter_to_feet<int, 10> = 30;

template<>
constexpr int meter_to_feet<int, 100> = 300;

int main()
{
cout << "1 米 : " << meter_to_feet<int, 1> << "英尺" << endl;
cout << "5 米 : " << meter_to_feet<int, 5> << "英尺" << endl;
cout << "10 米 : " << meter_to_feet<int, 10> << "英尺" << endl;
cout << "100 米 : " << meter_to_feet<int, 100> << "英尺" << endl;
cout << "200 米 : " << meter_to_feet<int, 200> << "英尺" << 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
#include <iostream>
#include <vector>
#include <limits>
#include <string>
using namespace std;

// 柱模板默认都不是数组
template<class T>
constexpr bool isarray = false;

// 偏特化
template<class T, size_t N>
constexpr bool isarray<T[N]> = true;

template<class T>
constexpr bool isarray<T[]> = true;

// 二维数组
template<class T, size_t N, size_t M>
constexpr bool isarray<T[N][M]> = true;


int main()
{
int value;
int arr1[22]{ 22 };
int arr2[]{ 22,44,66 };
int arr3[][4]{ 22,44,66 };
int* ptr = arr1;

cout << "value:" << isarray<decltype(value)> << endl;
cout << "value:" << isarray<decltype(arr1)> << endl;
cout << "value:" << isarray<decltype(arr2)> << endl;
cout << "value:" << isarray<decltype(arr3)> << endl;
cout << "value:" << isarray<decltype(ptr)> << 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
#include <iostream>
#include <vector>
#include <limits>
#include <string>
using namespace std;

// 判断类型是否一样的
template<class T, class K>
constexpr bool issame = false;

template<class T>
constexpr bool issame<T, T> = true;

template<class T, class U>
constexpr bool issame<const T, U> = issame<T, U>; // 递归调用,重载决议

template<class T, class U>
constexpr bool issame<T, const U> = issame<T, U>; // 递归调用,重载决议

int main()
{
int x = 10;
int y = 10;
cout << issame<int, decltype(x)> << endl;
cout << issame<int, const int > << endl;
cout << issame<const int, int > << endl;
cout << issame<double, int > << 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 <limits>
#include <string>
using namespace std;

template<class T>
constexpr int level = 10;

template<class T>
constexpr int level<T*> = 1;

template<class T>
constexpr int level<T**> = 2;

template<>
constexpr int level<int*> = 3;

int main()
{
// 全特化 大于 偏特化
cout << level<int*> << endl;
// 偏特化 大于 主模板
cout << level<int**> << endl;

return 0;
}

8 透明操作符函数对象

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
69
70
71
72
73
74
75
#include <iostream>
#include <vector>
#include <limits>
#include <string>
using namespace std;

// 透明操作符函数对象-->优化程序-->减少拷贝
// 函数对象:仿函数,重载了operator=的对象,实例化的对象。
// 函数对象:1.当做函数一样调用 2.存储状态 3.可以模板化 4.做类型,当做函数参数。

class add
{
public:
int operator()(int a, int b)
{
count = a + b;
return count;
}

// 函数的状态
int count = 10;
};

template<class T>
class add2
{
public:
T operator()(T a, T b)
{
count = a + b;
return count;
}

// 函数的状态
T count = T();
};
template<class T>
class add3
{
public:
T operator()(T a, T b)
{
count = a * b;
return count;
}

// 函数的状态
T count = T();
};

template<class T, class func>
int cal(T a, T b, func f)
{
return f(a, b);
}

void test()
{
add a;
cout << a(1, 3) << endl;

add2<int> a2;
cout << a2(2, 3) << endl;

cout << cal<int, add>(3, 3, a) << endl;
cout << cal<int, add2<int>>(4, 3, a2) << endl;

add3<int> a3;
cout << cal<int, add3<int>>(4, 3, a3) << endl;
}

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
43
44
45
#include <iostream>
#include <vector>
#include <limits>
#include <string>
using namespace std;

// 透明操作符函数对象-->优化程序-->减少拷贝
// 函数对象:仿函数,重载了operator=的对象,实例化的对象。
// 函数对象:1.当做函数一样调用 2.存储状态 3.可以模板化 4.做类型,当做函数参数。

// 函数对象 三大类

// 非透明
template<class T>
class myplus
{
public:
T operator()(const T& a, const T& b)
{
return a + b;
}
};

myplus<int> p1;
myplus<double> p2;
myplus<string> p3;

// 透明版本
template<>
class myplus<void>
{
using is_transparent = void; // 标签,标记支持异构处理(不同类型的处理)
template<class T, class U>
decltype(auto) operator()(T&& a, U&& b)
{
return forward<T>(a) + forward<U>(b);
}
};

myplus<void> p4;

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
#include <iostream>
#include <set>
#include <map>
#include <string>
using namespace std;

void test()
{
set<string, less<string>> s1;
set<string, less<>> s2;

// 1.不需要创建临时对象
s1.find("hello"); // 隐士类型转换
s2.find("world"); // 万能引用+完美转发

// 2.不同的类型数据(异构类型) 进行统一的操作。
map<string, int,greater<>> m1;
m1["apple"] = 1;
m1["banana"] = 2;
m1["carrort"] = 3;

auto it1 = m1.find("apple"); // 高效,不产生临时对象
auto it2 = m1.find("apple"s); // 高效,不产生临时对象
auto it3 = m1.find(string_view("carrot")); // // 高效,不产生临时对象 c++17

// 3自动类型推导
std::plus<> add;
auto result1 = add(3, 5);
auto result2 = add(3, 5.2);
auto result3 = add(3.4, 5);
auto result4 = add("hello"s, " lic");
}

int main()
{
test();

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
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <numeric>
#include <algorithm>
using namespace std;

void test()
{
// 1.做回调函数使用
vector<int> num1{ 1,2,3,4,5,6,7 };
vector<double> num2{ 1.2,2.3,3.5,4.6,5.7,6.7,7.7 };
vector<string> num3{ "lic1 ", "lic2", "lic3"};

auto sum1 = accumulate(num1.begin(), num1.end(), 0, plus<>{});
auto sum2 = accumulate(num2.begin(), num2.end(), 0.0, plus<>{});
auto sum3 = accumulate(num3.begin(), num3.end(), string(), plus<>{});

cout << "sum1:" << sum1 << endl;
cout << "sum2:" << sum2 << endl;
cout << "sum3:" << sum3 << endl;
}

template<class T, class U = less<>>
void sortContainer(T& c, U&& u = U())
{
sort(c.begin(), c.end(), forward<U>(u));
}


void test2()
{

auto print = [](auto& con)
{
for (auto i : con)
{
cout << i << " ";
}
cout << endl;
};

// 通用的排序
vector<int> num1{ 1,2,3,4,5,6,7 };
vector<double> num2{ 1.2,2.3,3.5,4.6,5.7,6.7,7.7 };
vector<string> num3{ "alic1", "clic2xxx", "alic3xxxxxx" };

sortContainer(num1);
sortContainer(num2);
sortContainer(num3);
print(num1);
print(num2);
print(num3);

sortContainer(num1, greater<>{});
sortContainer(num2, greater<>{});
sortContainer(num3, greater<>{});
print(num1);
print(num2);
print(num3);


// 自己写
sortContainer(num1, [](double a, double b) { return a < b;});
sortContainer(num3, [](const string& a, const string& b) { return a.length() < b.length();});
print(num1);
print(num3);

}

int main()
{
test2();

return 0;
}

9 智能指针

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
#include <iostream>
#include <memory>
#include <string>
using namespace std;

// 智能指针:防止内存泄漏
// 创建方式

class test
{
public:
test(int id, const string& name)
:_id(id)
,_name(name)
{ }

//test(){}
test() = default;

private:
int _id;
string _name;
};

template<class T, typename... Arg>
unique_ptr<T> myunique(Arg&& ...args)
{
return unique_ptr<T>(new T(forward<Arg>(args)...));
}

int main()
{
// c11
unique_ptr<int> ptr1{ new int{223} };
unique_ptr<test> ptr2{ new test{223, "lic"} };
unique_ptr<test> ptr3{ new test(223, "lic") };
unique_ptr<test> ptr4 = std::move(ptr3); // 独占,只能够交换所有权限

auto ptr5 = myunique<int>(44);
auto ptr6 = myunique<test>(44, "ssss"s);

// c14
auto ptr7 = make_unique<test>(44, "sss"s);
auto ptr8 = make_unique<int>(44);

// c14管理数组
//数组
// ()中的数字代表数组的元素个数
// 模板参数类型必须是T[],[]不能丟,通过 delete[]释放内存
// 数组元素初始化,使用默认构造函数
auto ptr9 = make_unique<int[]>(12); // 数组,元素12个;
auto ptr10 = make_unique<test[]>(22); // 数组,元素22个; 自定义一个无参数的构造函数

return 0;
}

10 读写锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;

// c++14:读写锁
// 读写锁:一个对象,一把锁。
// 怎么看读写锁:一个锁,三个状态。无锁,读锁(共享锁),写锁(独占锁)。
// 使用机制:读共享,写独占。
// 共享模式只能进行读操作。

// 1.shared_timed_mutex:读写类
// 2.shared_lock:读锁管理器。读模式下的加锁和解锁
// 3.unique_lock:写锁管理器。写模式下的加锁和解锁

int main()
{

return 0;
}