C++ 11

1.共享智能指针

智能指针:模板类。

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

class test
{
public:
test()
{
cout << "test()" << endl;
}

test(int x)
:_num(x)
{
cout << "test(int x) : " << x << endl;
}

test(string str)
{
cout << "test(string str : " << str << endl;
}

~test()
{
cout << "~test()" << endl;
}

private:
int _num;
};

int main()
{
// 1.开辟堆内存初始化
shared_ptr<int> ptr1(new int{ 44 });
shared_ptr<int[]> ptr2(new int[5]{ 44 }); // 注意c++11不支持数组,无法全部进行析构的

cout << "ptr1的引用计数:" << ptr1.use_count() << endl; // 1
cout << "ptr2的引用计数:" << ptr2.use_count() << endl; // 1

// 2.拷贝构造
shared_ptr<int> ptr3 = ptr1;
shared_ptr<int[]> ptr4(ptr2);
cout << "ptr1的引用计数:" << ptr1.use_count() << endl; // 2
cout << "ptr2的引用计数:" << ptr2.use_count() << endl; // 2
cout << "ptr3的引用计数:" << ptr3.use_count() << endl; // 2
cout << "ptr4的引用计数:" << ptr4.use_count() << endl; // 2

// 2.1移动构造(右值进行初始化)
shared_ptr<int> ptr5 = move(ptr3);
shared_ptr<int[]> ptr6(move(ptr4));
cout << "ptr1的引用计数:" << ptr1.use_count() << endl; // 2
cout << "ptr2的引用计数:" << ptr2.use_count() << endl; // 2
cout << "ptr3的引用计数:" << ptr3.use_count() << endl; // 0
cout << "ptr4的引用计数:" << ptr4.use_count() << endl; // 0
cout << "ptr5的引用计数:" << ptr5.use_count() << endl; // 2
cout << "ptr6的引用计数:" << ptr6.use_count() << endl; // 2

// 3.make_share 模板函数
shared_ptr<int> ptr7 = make_shared<int>(55);
shared_ptr<test> ptr8 = make_shared<test>(6); // 只需要类型,然后构造函数需要的参数类型。
shared_ptr<test> ptr9 = make_shared<test>("cccccccccc");
shared_ptr<test> ptr10 = make_shared<test>();
cout << "ptr10的引用计数:" << ptr10.use_count() << endl; // 1

// 4.reset方法。释放自己的所有权。可以管理新的内存。
ptr10.reset();
cout << "ptr10的引用计数:" << ptr10.use_count() << endl; // 0

ptr10.reset(new test("licher"));
cout << "ptr10的引用计数:" << ptr10.use_count() << endl; // 1

return 0;
}

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

class test
{
public:
test()
{
cout << "test()" << endl;
}

test(int x)
:_num(x)
{
cout << "test(int x) : " << x << endl;
}

test(string str)
{
cout << "test(string str : " << str << endl;
}

void print()
{
cout << "hello test" << endl;
}

~test()
{
cout << "~test()" << endl;
}

private:
int _num;
};

int main()
{
shared_ptr<test> ptr1(new test(10));
shared_ptr<test> ptr2 = make_shared<test>("lichermionex");

// 1.取出原始地址(当做对象使用)
test* p = ptr1.get();
p->print();

// 2.当做指针使用(直接当做指针使用)
ptr1->print();

return 0;
}

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <memory>
using namespace std;

class test
{
public:
test()
{
cout << "test()" << endl;
}

test(int x)
:_num(x)
{
cout << "test(int x) : " << x << endl;
}

test(string str)
{
cout << "test(string str : " << str << endl;
}

void print()
{
cout << "hello test" << endl;
}

~test()
{
cout << "~test()" << endl;
}

private:
int _num;
};

int main()
{
// 单个类型随便用
//shared_ptr<test> ppp(new test(100), [](test* t){
// cout << "------------" << endl;
// delete t;
// });

// 数组类型需要自定义删除器函数
shared_ptr<test> ppp(new test[5], [](test* t) {
cout << "------------" << endl;
delete[] t;
});

shared_ptr<test> ppp2(new test[5], [](test* t) {
cout << "------------" << endl;
delete[] t;
});

// 默认删除函数
shared_ptr<int> p1(new int[10] {0}, default_delete<int[]>());
shared_ptr<test> p2(new test[10], default_delete<test[]>());

return 0;
}

1.4 总结

1
2
3
1.智能指针:模板类,这样子就可以管理任意类型的指针指向的内存。
2.初始化,需要开辟堆内存。可以赋值或者拷贝。
3.c++11管理数组需要指定删除函数。

2.独享智能指针

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

int main()
{
// 1.初始化
unique_ptr<int> ptr1(new int{ 33 }); // 堆内存初始化

// 2.移动方式。将亡值,纯右值。
unique_ptr<int> ptr2(move(ptr1));
unique_ptr<int> ptr3 = move(ptr2);

// 3.reset方法
ptr3.reset(); // 释放资源了
ptr3.reset(new int{ 555 }); // 重新初始化资源
ptr3.reset(new int{ 444 }); // 再一次重新初始化资源

// 原始指针
int* p = ptr3.get();
cout << *p << endl; // 输出444
cout << *ptr3 << endl;

return 0;
}

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

class test
{
public:
test()
{
cout << "test()" << endl;
}

test(int x)
:_num(x)
{
cout << "test(int x) : " << x << endl;
}

test(string str)
{
cout << "test(string str : " << str << endl;
}

void print()
{
cout << "hello test" << endl;
}

~test()
{
cout << "~test()" << endl;
}

private:
int _num;
};

int main()
{
using ptrFunc = void(*)(test*);
unique_ptr<test,ptrFunc> ptr(new test("cccc"), [](test* t) {
cout << "-----1" << endl;
delete t;
});

unique_ptr<test, function<void(test*)>> ptr2(new test("cccc"), [=](test* t) {
cout << "-----2" << endl;
delete t;
});

// 独占指针,能够管理数组
unique_ptr<test[]> ptr3(new test[3]);

// 在c++11不支持管理数组类型的地址,C++11以后才支持的。
shared_ptr<test[]> ptr3(new test[3]);

return 0;
}

1.3 总结

1
2
3
1.同共享智能指针。
2.C++11就可以管理数组了的。
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
#include <iostream>
#include <memory>
using namespace std;

int main()
{
// 1.shared_ptr管理this对象
// 2.循环引用

// 初始化
shared_ptr<int> sp(new int{ 55 });

weak_ptr<int> wp1;
weak_ptr<int> wp2(wp1);
weak_ptr<int> wp3(sp);

weak_ptr<int> wp4;
wp4 = sp;
weak_ptr<int> wp5;
wp5 = wp3;

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

class test
{
public:
test()
{
cout << "test()" << endl;
}

void print()
{
cout << "Hello world" << endl;
}

~test()
{
cout << "~test()" << endl;
}
};

int main()
{

shared_ptr<test> t1(new test);

weak_ptr<test> t2 = t1;
weak_ptr<test> t3(t1);

if (auto p = t2.lock()) // 引用计数+1;
{
cout << p.use_count() << endl;
p->print();
}
else
{
cout << "对象已经不存在了" << endl;
}

cout << t1.use_count() << endl;

cout << t2.expired() << endl; //
cout << t3.expired() << 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
#include <iostream>
#include <memory>
using namespace std;

struct TA;
struct TB;

struct TA
{
//shared_ptr<TB> bptr;
weak_ptr<TB> bptr;
~TA()
{
cout << "~TA" << endl;
}
};

struct TB
{
shared_ptr<TA> aptr;
~TB()
{
cout << "~TB" << endl;
}
};

int main()
{
shared_ptr<TA> ap(new TA);
shared_ptr<TB> bp(new TB);

cout << "TA USE_COUNT : " << ap.use_count() << endl;
cout << "TB USE_COUNT : " << bp.use_count() << endl;

ap->bptr = bp;
bp->aptr = ap;

cout << "TA USE_COUNT : " << ap.use_count() << endl;
cout << "TB USE_COUNT : " << bp.use_count() << 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
#include <iostream>
#include <memory>
using namespace std;

class test: public enable_shared_from_this<test>
{
public:

shared_ptr<test> getSharePtr()
{
//return shared_ptr<test>(this);

// 返回共享当前对象所有权的 shared_ptr
return shared_from_this(); // 返回弱引用。外面已经有共享指针保存了。才能正确返回的。
}

~test()
{
cout << "~test()" << endl;
}
};

int main()
{
// 1.erro 原始地址初始化多次智能指针。会析构两次。两个智能指针同时管一块空间的。
//int* p = new int{ 22 };
//shared_ptr<int> ptr1(p);
//shared_ptr<int> ptr2(p);

//test* t = new test;
//shared_ptr<test> ptr3(t);
//shared_ptr<test> ptr4(t);

// 2.我们已经用 shared_ptr 管理了一个对象,
// 现在希望在对象自己的成员函数内部,再返回一个指向自己的 shared_ptr。
shared_ptr<test> sp1(new test);
shared_ptr<test> sp2 = sp1->getSharePtr(); // sp1初始化sp2
cout << sp1.use_count() << endl; // 计数是1
cout << sp2.use_count() << endl; // 计数是1

return 0;
}

4 POD类型

平凡类型:类的默认六大函数 + 没有虚函数 + 没有虚基类(虚继承的对象)。

1
2
3
4
5
6
7
8
9
int main()
{
// 1平凡类型:默认的六大函数。平凡的pod类型。
// 1.1平凡的构造和析构函数。 (默认的)
// 1.2平凡的拷贝构造和移动构造函数 (默认的)
// 1.3平凡的拷贝赋值和移动赋值运算 (默认的)
// 1.4不包含虚函数和虚基类(多重继承的时候,虚继承(virtual继承)。)
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 <type_traits>
using namespace std;

class test
{
public:
test() = default;
~test() = default;

test(const test&) = default;
test(test&&) = default;

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

// 1.没有虚函数
// 2.没有虚基类(继承的时候,虚继承的基类)
};

int main()
{
cout<< "test 平凡pod类型 " << is_trivial<test>::value <<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>
using namespace std;

struct Base { static int a; };
struct Child : public Base { int b; }; // pod类型

struct Base1 { int a; };
struct Child2 : public Base { static int b; }; // pod类型

struct Child3 : public Base, public Base1 { static int d; }; // pod类型
struct Child4 : public Base1 { int d; }; // 不是pod类型

// 两个基类同时出现非静态成员
struct Child4 : public Base1, public Child
{
static int num;
};

int main()
{
// 2标准布局
// 2.1--所有的非静态成员有相同的权限。
// 2.2继承关系的时候,基类和派生类只能一个出现非静态成员。多重继承也只能一个出现非静态成员。
// 非静态成员只能出现在基类或者派生。
// 非静态成员不能够出现在多个基类里面的。多重继承。
// 2.3派生类的第一个类型不是基类的类型
// 2.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
```







**模板函数的测试**

```c++
#include <iostream>
#include <type_traits>
using namespace std;

struct Base { static int a; };
struct Child : public Base { int b; }; // pod类型

struct Base1 { int a; };
struct Child2 : public Base { static int b; }; // pod类型

struct Child3 : public Base, public Base1 { static int d; }; // pod类型
struct Child4 : public Base1 { int d; }; // 不是pod类型

class test
{
// 六大函数都是默认的
test() = default;
test(int x){}
};

int main()
{
// 平凡类型
cout << "test是不是平凡的POD类型 : " << is_trivial<test>::value << endl;

// 标准布局
cout << "标准布局类型 : " << is_standard_layout<Base>::value << endl;

return 0;
}

5 default 和 delete

default :只能是对象的六大函数。

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

class A
{
public:
A() = default; // 默认的构造函数
~A() = default; // 默认的析构函数

A(const A&) = default; // 默认的拷贝构造
A(A&&) noexcept = default; // 默认的移动构造

A& operator=(const A&) = default; // 默认的拷贝赋值(拷贝赋值运算符)
A& operator=(A&&) noexcept = default; // 默认的移动赋值(移动赋值运算符)
};

int main()
{
return 0;
}

delete : 删除默认函数

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

class A
{
public:
A() = default; // 默认的构造函数
~A() = default; // 默认的析构函数

A(const A&) = delete; // 默认的拷贝构造
A(A&&) noexcept = delete; // 默认的移动构造

A& operator=(const A&) = delete; // 默认的拷贝赋值(拷贝赋值运算符)
A& operator=(A&&) noexcept = delete; // 默认的移动赋值(移动赋值运算符)

void print(int num)
{
cout << "num : " << num << endl;
}

void print(char ch) = delete;
};

int main()
{
A().print(22);
//A().print('a'); 防止隐士类型的转换

return 0;
}

6 友元

c++11 声明类的时候,可以减少class关键字。

友元可以使用别名了的。

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

class Tom;
using Honey = Tom;

class Jack
{
friend Tom;
private:
string name = "jack";
void print()
{
cout << "my name is " << name << endl;
}
};

class Lucy
{
friend Honey;
private:
string name = "lucy";
void print()
{
cout << "my name is " << name << endl;
}
};

class Tom
{
public:
void print()
{
cout << j.name << " : " << l.name << endl;
j.print();
l.print();
}

private:
Jack j;
Lucy l;
};

int main()
{
Tom t;
t.print();

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

template<class T>
class Rectangle
{
friend T;
public:
Rectangle(int width, int height)
:_width(width)
,_height(height)
{ }

private:
int _width;
int _height;
};

template<class T>
class Circle
{
friend T;
public:
Circle(int radius)
:_radius(radius)
{ }

private:
int _radius;
};

// 第三个类校验前面两个类的信息
class verify
{
public:
verify(int w, int h, Rectangle<verify>& r)
{
if (r._width > w && r._height > h)
{
cout << "矩形的宽度和高度符合要求" << endl;
}
else
{
cout << "矩形的宽度和高度不不符合要求" << endl;
}
}

verify(int r, Circle<verify>& c)
{
if (c._radius < r)
{
cout << "圆的半径符合要求" << endl;
}
else
{
cout << "圆的半径不符合要求" << endl;
}
}
};

int main()
{
Rectangle<verify> rect(100, 100);
Circle<verify> circle(90);

verify(100, 200, rect);
verify(50, circle);

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

// 缺陷:就是可见的范围太大了。C++需要空间指定。
enum test{ Red, Green, Blue };
enum Color1{ Red2, Green2, Blue2 };
enum class Color2 { Red, Green, Blue };
enum struct Color3 { Red, Green, Blue }; // 指定作用域

// 1.强作用域
// 2.禁止隐士类型转换,需要自己显示的类型转换。
// 3.指定类型

enum struct Color4 : char { Red, Green, Blue }; // 指定类型

int main()
{
//cout << "Red : " << Red << endl;
//cout << "Green : " << Green << endl;

cout << "Color2::Red2 : " << (int)Color2::Red << endl;
cout << "Color2 size :" << sizeof(Color2::Red) << endl;
cout << "Color4 size :" << sizeof(Color4::Red) << 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
#include <iostream>
#include <string>
using namespace std;

class Base
{
public:
Base(){}
};

union test
{
// 不允许非pod类型作为数据成员 c98
//string str;
//Base b;
// 不允许出现静态成员(成员属性和成员方法) c98
static int num;
int num2;
static void print()
{
num = 999;
} // 只能访问静态成员属性。

// 不允许出现引用,c11 也不行
};

int test::num = 0;

int main()
{
// 静态成员属性

test::print();

test t1;

t1.num2 = 222;
cout << "static int num : " << t1.num << endl;
cout << "int num2 : " << t1.num2 << endl;

test t2;
t2.num2 = 444;
cout << "static int num : " << t2.num << endl;
cout << "int num2 : " << t2.num2 << endl;



return 0;
}

定位放置new 解决非 POD类型

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 test
{
public:
test(){}
void settest(string s)
{
_name = s;
}

private:
string _name;
};

union Student
{
Student()
{
new (&_name)string;
}
~Student(){}

int _id;
string _name;
test t;
};

int main()
{
// 1.定位放置new可以是堆栈
// 2.已经存在的内存
// 3.自定调用对象的构造函数,无参构造
// 4.内存的重复创建和销毁

Student s;
s._name = "lic";
s.t.settest("lic2");
cout << "s._name:" << s._name << 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
61
62
63
64
65
66
67
68
#include <iostream>
#include <string>
using namespace std;

class Foreigner
{
public:
Foreigner(string a, string b)
:addr(a)
,phone(b)
{ }
string addr;
string phone;
};

class person
{
public:
enum class category : char {student, local, fore};

person(int num)
:number(num)
,c(category::student)
{ }

person(string str)
:idnum(str)
,c(category::local)
{ }

person(string a, string b)
:fore(a,b)
,c(category::fore)
{ }

void print()
{
switch (c)
{
case category::student:

break;
case category::local:

break;
case category::fore:

break;
}
}

~person()
{ }

private:
union
{
int number;
string idnum;
Foreigner fore;
};
category c;
};

int main()
{
return 0;
}

8 处理时间的库

8.1 duration

时间库 chrono: 时间间隔, 时钟, 时间点。

duration的基本定义

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

int main()
{
// 1.duration模板类。时间间隔,时间周期。
// 1小时
duration<int, ratio<3600, 1>> hour(1);
hours h(4);

// 1分钟
duration<int, ratio<60, 1>> min(1);
minutes m(1);

// 1秒
duration<int, ratio<1, 1>> minn(1);
seconds s(1);

// 1.毫秒
duration<int, ratio<1,1000>> min2(1);
milliseconds msec(1);

// 1微秒
duration<int, ratio<1,1000000>> min3(1);
microseconds mirco(1);

// 1.纳秒
duration<int, ratio<1,1000000000>> min4(1);
nanoseconds nana(1);

duration<double> sec1(2.5); // 2.5秒

cout << "时间周期:" << sec1.count() << endl;
cout << "时间周期:" << h.count() << endl;

return 0;
}

duration的重载方法。

分组最大公约数,分母最小的公倍数。

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

int main()
{
// 1.duration模板类。时间间隔,时间周期。
minutes m1(9);
minutes m2(8);
m1++;
m2--;
minutes m3 = m1 - m2; // 3

duration<int, ratio<60, 1>> t1(60); // 最大公约数,最小公倍数。
duration<int, ratio<1, 1>> t2(60);
//auto t3 = t1 - t2;
duration<int, ratio<1, 1>> t3 = t1 - t2;

duration<double, ratio<9, 7>> d1(3);
duration<double, ratio<6, 5>> d2(1);
duration<double, ratio<3, 35>> d3 = d1 - d2; //

cout << "时钟周期:" << d3.count() << endl;

return 0;
}

8.2 system_clock

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

void fun()
{
// 创建一个时间点对象
system_clock::time_point epoch; //

hours h(10 * 24);
system_clock::time_point epoch1 = epoch + h;
system_clock::time_point epoch2(epoch + h);

// 当前时间
system_clock::time_point nowtime = system_clock::now();

// 时间点转换时间段(秒)
time_t allsec = system_clock::to_time_t(nowtime);

cout << "当前时间:" << ctime(&allsec); // 格式化时间

system_clock::time_point tp = system_clock::from_time_t(allsec);
}

int main()
{
// 时间点+时间段。
fun();
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 <chrono>
using namespace std;
using namespace chrono;

void fun()
{
auto p1 = steady_clock::now();
for (int i = 0; i < 1000; ++i)
{

}
auto p2 = steady_clock::now();

auto d1 = p2 - p1;

cout << "count:" << d1.count() << endl;
}

// high_resolution_clock

int main()
{
fun();

return 0;
}

8.3转换函数

9 C11线程

9.1 this_thread

获取线程id

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

void func()
{
cout << "子线程id:" << this_thread::get_id() << endl;
}

int main()
{
cout << "主线程id:" << this_thread::get_id() << endl;

thread t(func);

t.join();

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

// 创建,就绪,运行,阻塞,退出。

void func()
{
for (int i = 0; i < 10; ++i)
{
this_thread::sleep_for(chrono::seconds(1)); // 参数:duration类型
cout << "i : " << i << endl;
}
}

int main()
{
cout << "我是主线,id:" << this_thread::get_id() << endl;

thread t(func);
t.join();

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

// 创建,就绪,运行,阻塞,退出。

void func()
{
for (int i = 0; i < 10; ++i)
{
//this_thread::sleep_for(chrono::seconds(1)); // 参数:duration类型,睡眠持续多久。

auto now = chrono::system_clock::now();
chrono::seconds sec(1);
this_thread::sleep_until(now + sec); // 睡眠到多久

this_thread::yield(); // 让出CUP的时间

cout << "i : " << i << endl;
}
}

int main()
{
cout << "我是主线,id:" << this_thread::get_id() << endl;

thread t(func);
t.join();

return 0;
}

9.2 thread

创建线程对象

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

void func1()
{
cout << "我是子线程,叫做lic1 ,id:" << this_thread::get_id() << endl;
}

void func2(string name, int age)
{
cout << "name : " << name << " : " << "age : " << age << "线程i:" << this_thread::get_id() << endl;
}

int main()
{
// 1.构造函数
// 空构造,移动构造,函数,拷贝构造(不允许,被删除了的)

thread t1; // 空对象,无参构造
thread t2(func1);
thread t3(func2, "lic", 22);
thread t4([](int id)
{
cout << "id : " << id << "线程i:" << this_thread::get_id() << endl;
}, 1001);

thread&& t5 = move(t4);

cout << "t2 id :" << t2.get_id() << endl;
cout << "t3 id :" << t3.get_id() << endl;
cout << "t4 id :" << t4.get_id() << endl;
cout << "t5 id :" << t5.get_id() << endl;

// 线程分离了,子线程退出了,主线程不需要回收子线程的资源。
//t2.detach();
//t3.detach();
//t5.detach();
// 不能够调用子线程的API了。

t2.join(); // 主线程,等待子线程执行完毕。阻塞主线程。执行完毕,解除阻塞。
t3.join(); // 主线程,等待子线程执行完毕。阻塞主线程。执行完毕,解除阻塞。
t5.join(); // 主线程,等待子线程执行完毕。阻塞主线程。执行完毕,解除阻塞。

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

void func1()
{
cout << "我是子线程,叫做lic1 ,id:" << this_thread::get_id() << endl;
}

void func2(string name, int age)
{
cout << "name : " << name << " : " << "age : " << age << "线程i:" << this_thread::get_id() << endl;
}

int main()
{
// 1.构造函数
// 空构造,移动构造,函数,拷贝构造(不允许,被删除了的)

thread t1; // 空对象,无参构造
thread t2(func1);
thread t3(func2, "lic", 22);
thread t4([](int id)
{
cout << "id : " << id << "线程i:" << this_thread::get_id() << endl;
}, 1001);

// 主线程和子线程是否相关
cout << "t1:" << t1.joinable() << endl;
cout << "t2:" << t2.joinable() << endl;
cout << "t3:" << t3.joinable() << endl;
cout << "t4:" << t4.joinable() << endl;



t2.join(); // 主线程,等待子线程执行完毕。阻塞主线程。执行完毕,解除阻塞。
t3.join(); // 主线程,等待子线程执行完毕。阻塞主线程。执行完毕,解除阻塞。
t4.join(); // 主线程,等待子线程执行完毕。阻塞主线程。执行完毕,解除阻塞。

cout << "t1:" << t1.joinable() << endl;
cout << "t2:" << t2.joinable() << endl;
cout << "t3:" << t3.joinable() << endl;
cout << "t4:" << t4.joinable() << endl;

return 0;
}

静态方法

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <thread>
using namespace std;

int main()
{
cout << thread::hardware_concurrency() << 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
#include <iostream>
#include <functional>
#include <thread>
#include <string>
using namespace std;

class test
{
public:
void showMsg(string name, int id)
{
cout << "name:" << name << ":" << "id:" << id << endl;
}

static void messgae()
{
cout << "至德者沉默,闻道者言说" << endl;
}
};

int main()
{
// 1静态方法属于对象
thread t1(&test::messgae);

// 2属于某个具体的对象
test t;
thread t2(&test::showMsg, &t, "lic", 22); // 可以取地址
thread t3(&test::showMsg, t, "lic", 23); // 可以实例

// bind
thread t4(bind(&test::showMsg, &t, "lic", 24)); // 可以取地址
thread t5(bind(&test::showMsg, t, "lic", 25)); // 可以实例

t1.join();
t2.join();
t3.join();
t4.join();
t5.join();

return 0;
}

call_once函数

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 <functional>
#include <thread>
#include <string>
#include <mutex>
using namespace std;

// 线程都能够看见的
once_flag flag;

void do_once(int a, int b)
{
cout << "a:" << a << endl;
cout << "b:" << b << endl;
}

void do_something(int id, string name)
{
cout << "id:" << id << endl;
cout << "name:" << name << endl;
call_once(flag, do_once, 1, 3); // 只会调用一次的。
}

int main()
{
thread t1(do_something, 1, "lic1");
thread t2(do_something, 3, "lic2");
thread t3(do_something, 2, "lic3");

t1.join();
t2.join();
t3.join();

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 <functional>
#include <thread>
#include <string>
#include <mutex>
using namespace std;

once_flag flag;

class Base
{
public:
Base(const Base& obj) = delete;
Base& operator=(const Base& obj) = delete;

static Base* getInstanc()
{
call_once(flag, [&]()
{
obj = new Base;
cout << "创建实例对象" << endl;
});

return obj;
}

void set(string name)
{
_name = name;
}

string get()
{
return _name;
}

private:
Base(){}
static Base* obj;
string _name;
};

Base* Base::obj = nullptr;

void func(string name)
{
Base::getInstanc()->set(name);
cout << "name:" << Base::getInstanc()->get() << endl;
}

int main()
{
thread t1(func, "lic1");
thread t2(func, "lic2");
thread t3(func, "lic3");
thread t4(func, "lic4");

t1.join();
t2.join();
t3.join();
t4.join();

return 0;
}

9.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
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;

// 1.互斥锁保护共享资源

class Base
{
public:
void increment(int count)
{
for (int i = 0; i < count; ++i)
{
_mutex.lock(); // 独占,自己加锁自己解锁。

_num++;
cout << "increment _num:" << _num << endl;

_mutex.unlock();

this_thread::sleep_for(chrono::milliseconds(500));
}
}

void decrement(int count)
{
for (int i = 0; i < count; ++i)
{
_mutex.lock();

_num--;
cout << "decrement _num:" << _num << endl;

_mutex.unlock();

this_thread::yield();
}
}

private:
int _num = 44;
mutex _mutex;
};

int main()
{
Base b;
thread t1(&Base::increment, &b, 100);
thread t2(&Base::decrement, &b, 100);

t1.join();
t2.join();

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

// 1.互斥锁保护共享资源

class Base
{
public:
void increment(int count)
{
for (int i = 0; i < count; ++i)
{
{
lock_guard<mutex> gurad(_mutex);

_num++;
cout << "increment _num:" << _num << endl;
}

this_thread::sleep_for(chrono::milliseconds(500));
}
}

void decrement(int count)
{
for (int i = 0; i < count; ++i)
{
{
lock_guard<mutex> gurad(_mutex);

_num--;
cout << "decrement _num:" << _num << endl;
}

this_thread::yield();
}
}

private:
int _num = 44;
mutex _mutex;

};

int main()
{
Base b;
thread t1(&Base::increment, &b, 10);
thread t2(&Base::decrement, &b, 10);

t1.join();
t2.join();

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 <thread>
#include <mutex>
#include <chrono>
using namespace std;

// 1.互斥锁保护共享资源

class Base
{
public:
void increment(int count)
{
for (int i = 0; i < count; ++i)
{

_mutex.lock();

_num++;
cout << "increment _num:" << _num << endl;

_mutex.unlock();

this_thread::sleep_for(chrono::milliseconds(500));
}
}

void decrement(int count)
{
for (int i = 0; i < count; ++i)
{
{
lock_guard<recursive_mutex> gurad(_mutex);

increment(2);

_num--;
cout << "decrement _num:" << _num << endl;
}

this_thread::yield();
}
}

private:
int _num = 44;
recursive_mutex _mutex;

};

int main()
{
Base b;
thread t1(&Base::increment, &b, 10);
thread t2(&Base::decrement, &b, 10);

t1.join();
t2.join();

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

// 1.互斥锁保护共享资源

class Base
{
public:
void increment(int count)
{
for (int i = 0; i < count; ++i)
{

_mutex.lock();

_num++;
cout << "increment _num:" << _num << endl;

_mutex.unlock();

this_thread::sleep_for(chrono::milliseconds(500));
}
}

void decrement(int count)
{
for (int i = 0; i < count; ++i)
{
{
lock_guard<recursive_mutex> gurad(_mutex);

increment(2);

_num--;
cout << "decrement _num:" << _num << endl;
}

this_thread::yield();
}
}

void work()
{
while (true)
{
if (_tmutex.try_lock_for(chrono::milliseconds(100)))
{
count++;
this_thread::sleep_for(chrono::milliseconds(500));
cout << "线程抢到互斥锁 线程id:" << this_thread::get_id() << endl;

_tmutex.unlock();

break;
}
else
{
cout << "线程没有抢到互斥锁 线程id:" << this_thread::get_id() << endl;
this_thread::sleep_for(chrono::milliseconds(500));
}
}
}

private:
int _num = 44;
int count = 0;
recursive_mutex _mutex;
timed_mutex _tmutex;
};

int main()
{
Base b;
thread t1(&Base::work, &b);
thread t2(&Base::work, &b);

t1.join();
t2.join();

return 0;
}

9.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
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
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <queue>
using namespace std;

// 1.生产者消费者模型。
// 2.条件变量:可以放行多个线程。
// 3.线程阻塞,等待资源。生产者:数据满了。消费者:数据空了。
// 4.任务队列需要保护起来的。

class task
{
public:
// 放数据
void put(int x)
{
unique_lock<mutex> locker(_mutex);

while(taskQueue.size() == _maxSize)
{
notfull.wait(locker);
}


taskQueue.push(x);
cout << "线程id" << this_thread::get_id() << " 添加任务:" << x << endl;

notempty.notify_one();
}

// 拿数据
void take()
{
unique_lock<mutex> locker(_mutex);

while (taskQueue.empty())
{
notempty.wait(locker);
}

int num = taskQueue.front();
taskQueue.pop();
cout << "线程id" << this_thread::get_id() << " 消费任务:" << num << endl;

notfull.notify_one();
}

bool isFull()
{
lock_guard<mutex> locker(_mutex);
if (taskQueue.size() == _maxSize)
{
return true;
}

return false;
}

bool isEmpty()
{
lock_guard<mutex> locker(_mutex);
if (taskQueue.size() == 0)
{
return true;
}

return false;
}

int taskSize()
{
lock_guard<mutex> locker(_mutex);
return taskQueue.size();
}

private:
int _maxSize = 100;
queue<int> taskQueue;
mutex _mutex; // 保护任务队列
condition_variable notfull;
condition_variable notempty;
};


int main()
{
// 1.任务队列。存放任务。
// 2.条件变量阻塞一类线程。这一类线程也必须使用互斥锁。

thread t1[5];
thread t2[5];
task taskqueue;

for (int i = 0; i < 5; ++i)
{
t1[i] = thread(&task::put, &taskqueue, 100 + i);
t2[i] = thread(&task::take, &taskqueue);
}

for (int i = 0; i < 5; ++i)
{
t1[i].join();
t2[i].join();
}

return 0;
}

wait方法带回调函数。

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
40
41
42
43
44
45
46
#include <iostream>
#include <atomic>
using namespace std;

// 读数据:磁盘 内存 缓存。。。。 CPU
// 写数据:CPU 缓存。。。。 内存 磁盘
// 原子操作:这三步不能够被拆分的。

// atomic:模板类。

struct base
{
int age;
char ch;
};

int main()
{
// 存储整型数据,初始化数据
atomic<int> t1;
atomic<int> t2(22);
atomic<char> t3('a');
atomic_char t4('b');

//atomic_init(&t1, 44);

// 修改数据
atomic<int> t5(55);
t5 = 44;
t5.store(33);
int c = t5.exchange(22); // 返回值

// 取数据
cout << "t5:" << t5 << endl;
cout << "c:" << c << endl;
cout << "t5.loacd:" << t5.load() << endl;

base b{ 1, 'c' };
atomic<base*> tt(&b);

base* temp = tt.load();
cout << "base 1 :" << temp->age << endl;
cout << "base 2 :" << temp->ch << 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
#include <iostream>
#include <atomic>
#include <thread>
#include <mutex>
using namespace std;

// 读数据:磁盘 内存 缓存。。。。 CPU
// 写数据:CPU 缓存。。。。 内存 磁盘
// 原子操作:这三步不能够被拆分的。

// atomic:模板类。

class test
{
public:
void increment()
{
for (int i = 0; i < 10000; ++i)
{
++number;
cout << "increment number:" << number << endl;
}
}

void decrement()
{
for (int i = 0; i < 10000; ++i)
{
--number;
cout << "decrement number:" << number << endl;
}
}

private:
//int number = 100;
atomic_int number = 100;
};

int main()
{
test t;
thread t1(&test::increment, &t);
thread t2(&test::decrement, &t);

t1.join();
t2.join();

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <atomic>
#include <thread>
#include <mutex>
using namespace std;

// 1.编译器可能对二进制指令进行重排
// 1.CPU可能对二进制指令进行重排
// 1.线程每次执行二进制的顺序不一样

int main()
{

return 0;
}

11 线程异步

image-20261108124847570

image-20261108124903873

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 <future>
#include <thread>
#include <chrono>
using namespace std;

// 线程A---等待线程B 阻塞:等待。 线程同步。
// 线程A做事情---顺便等待线程B。 做自己的事情,线程异步。

// future存储返回值。
// prromise赋值
// packaged_task赋值

int add(int x, int y)
{
cout << "子线程" << this_thread::get_id() << endl;
this_thread::sleep_for(chrono::seconds(3));
return x + y;
}

int main()
{
// 1.启动异步线程执行函数
future<int> fur = async(launch::async, add, 33, 44);
cout << "主线程" << this_thread::get_id() << endl;
cout << "我是主线程" << endl;
// 2.等待异步线程完成任务。
int result = fur.get(); // 会阻塞的

cout << "result:" << result << 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
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
using namespace std;

// 线程A---等待线程B 阻塞:等待。 线程同步。
// 线程A做事情---顺便等待线程B。 做自己的事情,线程异步。

// future存储返回值。
// prromise赋值
// packaged_task赋值

int add(int x, int y)
{
cout << "子线程" << this_thread::get_id() << endl;
this_thread::sleep_for(chrono::seconds(3));
return x + y;
}

int main()
{
// 1.启动异步线程执行函数
future<int> fur = async(launch::async, add, 33, 44);
cout << "主线程" << this_thread::get_id() << endl;
cout << "我是主线程" << endl;
// 2.等待异步线程完成任务
fur.wait();
int result = fur.get();

cout << "result : " << result << 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
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
using namespace std;

// 线程A---等待线程B 阻塞:等待。 线程同步。
// 线程A做事情---顺便等待线程B。 做自己的事情,线程异步。

// future存储返回值。
// prromise赋值
// packaged_task赋值

int add(int x, int y)
{
cout << "子线程" << this_thread::get_id() << endl;
this_thread::sleep_for(chrono::seconds(3));
return x + y;
}

int main()
{
// 1.启动异步线程执行函数
future<int> fur = async(launch::async, add, 33, 44);
cout << "主线程" << this_thread::get_id() << endl;
cout << "我是主线程" << endl;
// 2.等待异步线程完成任务
auto status = fur.wait_for(chrono::seconds(10));
if (status == future_status::ready)
{
cout << fur.get() << endl;
}
else if(status == future_status::timeout)
{
cout << "任务还没有执行完" << endl;
}
else if(status == future_status::deferred)
{
cout << "任务尚未执行,属于延迟执行" << 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 <thread>
#include <future>
using namespace std;

void worker(promise<int> p)
{
int result = 10 + 20;
p.set_value(result);
}

int main()
{
promise<int> p;

// 获取关联的 future
future<int> fut = p.get_future();

// promise 不可复制,只能移动
thread t(worker, move(p));

// 等待子线程传递结果
cout << fut.get() << endl;

t.join();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

#include <iostream>
#include <future>
#include <thread>
using namespace std;

int add(int a, int b)
{
return a + b;
}

int main()
{
packaged_task<int(int, int)> task(add);

future<int> fut = task.get_future();

thread t(move(task), 10, 20);

cout << fut.get() << endl;

t.join();
}

12 万能引用

万能引用

  1. 模板类型推导
  2. 引用折叠(Reference Collapsing)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;

template<class T>
void func(T&& value)
{
cout << "value:" << value << endl;
}

int main()
{
func<int>(10);
int a = 22;
func<int>(std::move(a));
int& b = a;
b = 4;
func<int>(std::move(b));

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

void print(int& value)
{
cout << "int&:" << value << endl;
}

void print(int&& value)
{
cout << "int&&:" << value << endl;
}

template<class T>
void func(T&& value)
{
// print(value);
print(forward<T>(value));
}

int main()
{
int a = 10;
func(a);
func(22);

return 0;
}

无论变量声明时的类型是左值引用还是右值引用,只要它是有名字的变量,作为表达式使用时就是左值。