抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

函数重载

如果一个作用域内几个函数名字相同但是参数列表不同, 称为函数重载与返回值没有关系

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
/*************************************************************************
> File Name: 11.reload.cpp
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年07月14日 星期四 18时53分58秒
************************************************************************/

#include <iostream>
using namespace std;

int func(int x) {
return 2 * x;
}

// 要把缺省值考虑进去 如:func(int x, int y = 2)
int func(int x, int y) {
return x * y;
}

double func(double x) {
return x + 1000;
}

int main() {
// 把一类可以通过参数区分的功能命名成同一个函数名->精细化的处理流程
// 参数相同返回值不通 == 不可以
// 参数类型不同or参数个数不同 == 可以
cout << func(2) << endl; // 通过参数 调用第一个
cout << func(2.0) << endl; // 调用第二个
return 0;
}
  • 重载的意义
    • 通过函数名对函数功能进行提示 ①
    • 通过函数参数列表对函数的用法进行提示 ②
    • 扩展已有的功能 ③

① ③ 如 abs(求整形绝对值)、fabs(浮点数绝对值)如果用重载实现

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

int ABS(int x) {
return abs(x);
}

double ABS(double x) {
return fabs(x);
}

int main() {
// ABS
cout << ABS(-3) << endl;
cout << ABS(-4.4) << endl;
return 0;
}

② 输出一个N个数字的全排列

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 <math.h>
#include <string.h>
using namespace std;

void output_permutation(int ind, int n, int *buff, int *num) {
if(ind == n) {
for(int i = 0; i < n; ++i) {
cout << buff[i] << " ";
}
cout << endl;
return ;
}
for(int i = 1; i <= n; i++) {
if(num[i]) continue;
buff[ind] = i;
num[i] = 1;
output_permutation(ind + 1,n ,buff, num);
num[i] = 0;
}
return ;
}

void output_permutation(int n) { // 接口
int num[n + 1], buff[n];
memset(num, 0, sizeof(num));
memset(buff, 0, sizeof(buff));
// 从0开始一个要枚举n位,把中间枚举的数字放在buff中num标记那个数字被使用了
output_permutation(0, n, buff, num); // 功能实现
return ;
}

int main() {
// 全排列
output_permutation(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
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
/*************************************************************************
> File Name: 11.reload.cpp
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年07月14日 星期四 18时53分58秒
************************************************************************/

#include <iostream>
#include <math.h>
#include <string.h>
using namespace std;

int func(int x) {
return 2 * x;
}

int func(int x, int y) {
return x * y;
}

double func(double x) {
return x + 1000;
}

int ABS(int x) {
return abs(x);
}

double ABS(double x) {
return fabs(x);
}

void output_permutation(int ind, int n, int *buff, int *num) {
if(ind == n) {
for(int i = 0; i < n; ++i) {
cout << buff[i] << " ";
}
cout << endl;
return ;
}
for(int i = 1; i <= n; i++) {
if(num[i]) continue;
buff[ind] = i;
num[i] = 1;
output_permutation(ind + 1,n ,buff, num);
num[i] = 0;
}
return ;
}

// 接口
void output_permutation(int n) {
int num[n + 1], buff[n];
memset(num, 0, sizeof(num));
memset(buff, 0, sizeof(buff));
// 从0开始一个要枚举n位,把中间枚举的数字放在buff中num标记那个数字被使用了
output_permutation(0, n, buff, num); // 功能实现
return ;
}

int main() {
// 把一类可以通过参数区分的功能命名成同一个函数名->精细化的处理流程
// 参数相同返回值不通 == 不可以
// 参数类型不同or参数个数不同 == 可以
cout << func(2) << endl; // 通过参数 调用第一个
cout << func(2.0) << endl; // 调用第二个

// ABS
cout << ABS(-3) << endl;
cout << ABS(-4.4) << endl;

// 全排列
output_permutation(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
/*************************************************************************
> File Name: 12.friend.cpp
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年07月14日 星期四 22时25分20秒
************************************************************************/

#include <iostream>
using namespace std;

class Point {

public :


Point(int x, int y) : x(x), y(y) {}
void output() {
cout << "inner : " << x << " " << y << endl;
return ;
}
// 声明类外隔壁老王 就可以在类外访问私有成员了
friend void output(Point &a);
friend ostream &operator<<(ostream &out, const Point &p);
private :
int x, y;

};

void output(Point &a) {
cout << "outer : " << a.x << " " << a.y << endl;
}

// cout(左面的参数) << p(右面的参数)
ostream &operator<<(ostream &out, const Point &p) {
out << "Point(" << p.x << ", " << p.y << ")";
return out;
}

int main() {
// 输出点类, 对象信息
Point p(3, 4);
p.output();
output(p);
cout << p;
return 0;
}

为什么有元函数要声明在类内部呢?

对方是否是“隔壁老王”这个事情不取决于对方而取决于自己 — 主要也是遵守代码的安全性

运算符重载(非成员)

  • C++中重载能够扩展运算符的功能
  • 运算符重载以函数的方式进行
  • 特殊形式的函数扩展运算符的功能

总结:重载运算符是扩展已有的功能,而不是新造一个运算符。

1
2
3
4
5
Type operater Sign(type &obj1, type &obj2) {
Type ret;
// do something
return ret;
}

Sign 是 +, -, *, /等

单目运算符只有一个参数,双面运算符有个参数

  • 双目:

    +,-,*,/,<<

  • 单目:

    ++,–,*(取值运算符)

  • 三目:

    ? :(问号冒号表达式)

什么符号能被重载?

+ - * / % ^
& | ~ ! , =
< > <= >= ++
<< >> == != && ||
+= -= *= /= ^= &=
|= %= <<= >>= [] ()
-> ->* (间接引用成员运算符) new new[] delete delete[]

运算符重载是如何区分前++后++ 的 如果有一个额外的参数那么就是后加++。

void operator ++(int); // 后++

void operator ++(); // ++前

不能被重载 :: (域运算符) .* (点星运算符) . (直接引用运算符) ?:(三目运算符) sizeof

运算符重载 // test2-代码实现

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*************************************************************************
> File Name: 12.friend.cpp
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年07月14日 星期四 22时25分20秒
************************************************************************/

#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(ttw)

class Point {

public :

Point operator+(const int &a) const {
// 创建一个临时变量,就不能返回引用 --- 画个重点可能要考 哈 哈哈!
return Point(this->x + a, this->y + a);
}

Point(int x, int y) : x(x), y(y) {
z1 = rand() % 100;
z2 = z1 + 1;
z3 = z2 + 1;
cout << this << " : rand value : " << z1 << endl;
}

void output() {
cout << "inner : " << x << " " << y << endl;
return ;
}

// +=
// 如果不返回引用 结果就会拷贝给一个临时变量返回
Point &operator +=(const int &x) {
this->x += x;
this->y += x;
return *this;
}

// 注意 这是后++ 列: p++ 如果有一个额外的参数那么就是后加++
Point operator ++(int ) {
Point ret(*this);
this->x += 1;
this->y += 1;
return ret;
}

Point &operator++() {
this->x += 1;
this->y += 1;
return *this;
}

// 声明类外隔壁老王 就可以在类外访问私有成员了
friend void output(Point &a);
friend ostream &operator<<(ostream &, const Point &);
friend Point operator+(const Point &, const Point &);
int z1, z2, z3;

private :
int x, y;

};

void output(Point &a) {
cout << "outer : " << a.x << " " << a.y << endl;
}

// cout(左面的参数) << p(右面的参数)
ostream &operator<<(ostream &out, const Point &p) {
out << "Point(" << p.x << ", " << p.y << ")";
return out;
}

// 类外重载加法运算符
Point operator+(const Point &a, const Point &b) {
/*
Point c(a.x + b.x, a.y + b.y);
return c;
*/
return Point(a.x + b.x, a.y + b.y);
}

ENDS(ttw)

BEGINS(test1)

using namespace ttw;

int main() {

srand(time(NULL));

// 输出点类, 对象信息
Point p(3, 4), q(5, 6);
p.output();
output(p);
cout << p << endl;
cout << (p + q) << endl;

// 去掉const 不对 p + q 会返回一个临时变量、因为临时变量是绑定 不上的
cout << (p + (p + q)) << endl;

// (3, 4) + 5 == (8, 9);
// p + 5 => p.operator+(5)
cout << (p + 5) << endl;

// const 对象 只能调用 const 方法
const Point z(1111, 123);
cout << z + 5 << endl;

// 间接引用运算符
Point *pp = &p;
int Point::* px = &Point::z1;
cout << pp->*px << endl;
px = &Point::z2;
cout << pp->*px << endl;
px = &Point::z3;
cout << pp->*px << endl;

return 0;
}

ENDS(test1)

BEGINS(test2)

using namespace ttw;

int mian() {

// +=
Point p(3, 4);
cout << ((p += 2) += 3) << endl;

// p++、++p
cout << "p++ : " << (p++) << endl;
cout << "p : " << p << endl;
// n = 4; 考虑(++n)++;
cout << "++p : " << (++p) << endl;
(++p)++;
cout << "(++p)++ : " << p << endl;

return 0;
}

ENDS(test2)

int main() {
// 友元
// test1::main();

// 重载运算符
test2::mian();

return 0;
}

1.数组对象(外在表现像个数组) // test3-代码实现 -> 主要重载[]

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 <stdlib.h>
#include <time.h>
using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(test3)

using namespace ttw;

class Array {

public :
Array(int n = 100) :n(n), data(new int[n]) {}
int &operator[](const int &ind) {
return data[ind];
}
int &operator[](const char *s) {
int ind = atoi(s);
return data[ind];
}
const int &operator[](const int &ind) const {
return data[ind];
}

private :
int n;
int *data;

};

int main() {
Array arr;
for(int i = 0;i < 10; i++) {
arr[i] = i;
}
for(int i = 0; i < 10; i++) {
cout << arr[i] << " ";
}
cout << endl;
const Array arr2;
for(int i = 0; i < 10; i++) {
cout << arr2[i] << " ";
}
cout << endl;
cout << arr["0"] << " " << arr["1"] << " " << arr["2"] << endl;

return 0;
}

ENDS(test3)

int main() {
// 1.数组对象 // test3
// 2.函数对象
// 3.指针对象
test3::main();

return 0;
}

2.函数对象(外咋表现像个函数) // test4-代码实现 -> 主要重载 ()

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 <stdlib.h>
#include <time.h>
#include <functional>
using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(test4)

class Function {

public :
int operator()(const int &a, const int &b) {
cout << "inner class : ";
return a + b;
}
private :

};


int fubc1(int a, int b) {
cout << "inner func1 : ";
return a + b;
}

// 类型不重要,外在表现很重要
int main() {

Function fuc;
cout << fuc(3, 4) << endl;

// 函数指针, 本质上它在指向拥有相同表现的
int (*p)(int ,int) = fubc1;
cout << p(3, 4) << endl;

// q 函数指针对象
function<int (int, int)> q;
q = fubc1;
cout << "q pointer : " << q(3, 4) << endl;
q = fuc;
cout << "q Point : " << q(3, 4) << endl;

return 0;
}

ENDS(test4)

int main() {
// 1.数组对象 // test3
// 2.函数对象 // test4
// 3.指针对象
//test3::main();
test4::main();
return 0;
}

3.指针对象(外在表现像个指针) // test5-代码实现 -> 1.->、2.*(取值)、3.+、4.-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
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
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <functional>
using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

// pointer_object
BEGINS(test5)


struct A{
A() : x(0), y(0) {}
int x, y;
};

ostream &operator<<(ostream &out, const A &a) {
out << a.x << " " << a.y << endl;
return out;
}

class Pointer {
public :
Pointer(A *p = nullptr) : p(p){}
A *operator->() { return p; }
A &operator *() { return *p;}
A &operator *() const { return *p;}
A *operator+(const int &n) const { return p + n; }
A *operator-(const int &n) const { return p - n; }
A *operator+(const int &n) { return p + n; }
A *operator-(const int &n) { return p - n; }
int operator-(const Pointer &p) { return this->p - p.p; }
A &operator[](int ind) { return *(p + ind); }
A &operator[](int ind) const { return *(p + ind); }
friend ostream &operator<<(ostream &, const Pointer &);
private :
A *p;
};

ostream &operator <<(ostream &out, const Pointer &a) {
out << a.p << endl;
return out;
}

void main() {
A a, b;
Pointer p = &a, q = &b;
cout << a;
p->x = 3;
p->y = 4;
cout << a;
cout << *p;

cout << p;
cout << (p + 1) << endl;
cout << (p - 1) << endl;

cout << " p : " << p;
cout << " q : " << q;

cout << "(p - q) : "<< (p - q) << endl;
cout << "p[0] : "<< p[0] << endl;

const Pointer cp = &a;
cout << *cp << endl;
cout << (cp + 1) << endl;
cout << (cp - 1) << endl;
cout << cp[0] << endl;

return ;
}

ENDS(test5)

int main() {
// 1.数组对象 // test3
// 2.函数对象 // test4
// 3.指针对象 // test5
//test3::main();
// test4::main();
test5::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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
/*************************************************************************
> File Name: 12.friend.cpp
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年07月14日 星期四 22时25分20秒
************************************************************************/

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <functional>
using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(ttw)


class Point {
public :

Point operator+(const int &a) const {
// 创建一个临时变量,就不能返回引用 --- 画个重点可能要考 哈哈哈!
return Point(this->x + a, this->y + a);
}

Point(int x, int y) : x(x), y(y) {
z1 = rand() % 100;
z2 = z1 + 1;
z3 = z2 + 1;
cout << this << " : rand value : " << z1 << endl;
}

void output() {
cout << "inner : " << x << " " << y << endl;
return ;
}

// +=
// 如果不返回引用 结果就会拷贝给一个临时变量返回
Point &operator +=(const int &x) {
this->x += x;
this->y += x;
return *this;
}

// 注意 这是后++ 列: p++ 如果有一个额外的参数那么就是后加++
Point operator ++(int ) {
Point ret(*this);
this->x += 1;
this->y += 1;
return ret;
}

Point &operator++() {
this->x += 1;
this->y += 1;
return *this;
}

// 声明类外隔壁老王 就可以在类外访问私有成员了
friend void output(Point &a);
friend ostream &operator<<(ostream &, const Point &);
friend Point operator+(const Point &, const Point &);
int z1, z2, z3;

private :
int x, y;

};

void output(Point &a) {
cout << "outer : " << a.x << " " << a.y << endl;
}

// cout(左面的参数) << p(右面的参数)
ostream &operator<<(ostream &out, const Point &p) {
out << "Point(" << p.x << ", " << p.y << ")";
return out;
}

// 类外重载加法运算符
Point operator+(const Point &a, const Point &b) {
/*
Point c(a.x + b.x, a.y + b.y);
return c;
*/
return Point(a.x + b.x, a.y + b.y);
}

ENDS(ttw)

BEGINS(test1)

using namespace ttw;

int main() {

srand(time(NULL));

// 输出点类, 对象信息
Point p(3, 4), q(5, 6);
p.output();
output(p);
cout << p << endl;
cout << (p + q) << endl;

// 去掉const 不对 p + q 会返回一个临时变量、因为临时变量是绑定不上 的
cout << (p + (p + q)) << endl;

// (3, 4) + 5 == (8, 9);
// p + 5 => p.operator+(5)
cout << (p + 5) << endl;

// const 对象 只能调用 const 方法
const Point z(1111, 123);
cout << z + 5 << endl;

// 间接引用运算符
Point *pp = &p;
int Point::* px = &Point::z1;
cout << pp->*px << endl;
px = &Point::z2;
cout << pp->*px << endl;
px = &Point::z3;
cout << pp->*px << endl;

return 0;
}

ENDS(test1)

BEGINS(test2)

using namespace ttw;

int main() {

// +=
Point p(3, 4);
cout << ((p += 2) += 3) << endl;

// p++、++p
cout << "p++ : " << (p++) << endl;
cout << "p : " << p << endl;
// n = 4; 考虑(++n)++;
cout << "++p : " << (++p) << endl;
(++p)++;
cout << "(++p)++ : " << p << endl;

return 0;
}

ENDS(test2)

// array_object
BEGINS(test3)

using namespace ttw;

class Array {

public :
Array(int n = 100) :n(n), data(new int[n]) {}
int &operator[](const int &ind) {
return data[ind];
}
int &operator[](const char *s) {
int ind = atoi(s);
return data[ind];
}
const int &operator[](const int &ind) const {
return data[ind];
}

private :
int n;
int *data;

};

int main() {
Array arr;
for(int i = 0;i < 10; i++) {
arr[i] = i;
}
for(int i = 0; i < 10; i++) {
cout << arr[i] << " ";
}
cout << endl;
const Array arr2;
for(int i = 0; i < 10; i++) {
cout << arr2[i] << " ";
}
cout << endl;
cout << arr["0"] << " " << arr["1"] << " " << arr["2"] << endl;

return 0;
}

ENDS(test3)

// function_object
BEGINS(test4)

class Function {

public :
int operator()(const int &a, const int &b) {
cout << "inner class : ";
return a + b;
}
private :

};


int fubc1(int a, int b) {
cout << "inner func1 : ";
return a + b;
}

// 类型不重要,外在表现很重要
int main() {

Function fuc;
cout << fuc(3, 4) << endl;

// 函数指针, 本质上它在指向拥有相同表现的
int (*p)(int ,int) = fubc1;
cout << p(3, 4) << endl;

// q 函数指针对象
function<int (int, int)> q;
q = fubc1;
cout << "q pointer : " << q(3, 4) << endl;
q = fuc;
cout << "q Point : " << q(3, 4) << endl;

return 0;
}

ENDS(test4)


// pointer_object
BEGINS(test5)


struct A{
A() : x(0), y(0) {}
int x, y;
};

ostream &operator<<(ostream &out, const A &a) {
out << a.x << " " << a.y << endl;
return out;
}

class Pointer {
public :
Pointer(A *p = nullptr) : p(p){}
A *operator->() { return p; }
A &operator *() { return *p;}
A &operator *() const { return *p;}
A *operator+(const int &n) const { return p + n; }
A *operator-(const int &n) const { return p - n; }
A *operator+(const int &n) { return p + n; }
A *operator-(const int &n) { return p - n; }
int operator-(const Pointer &p) { return this->p - p.p; }
A &operator[](int ind) { return *(p + ind); }
A &operator[](int ind) const { return *(p + ind); }
friend ostream &operator<<(ostream &, const Pointer &);
private :
A *p;
};

ostream &operator <<(ostream &out, const Pointer &a) {
out << a.p << endl;
return out;
}

void main() {
A a, b;
Pointer p = &a, q = &b;
cout << a;
p->x = 3;
p->y = 4;
cout << a;
cout << *p;

cout << p;
cout << (p + 1) << endl;
cout << (p - 1) << endl;

cout << " p : " << p;
cout << " q : " << q;

cout << "(p - q) : "<< (p - q) << endl;
cout << "p[0] : "<< p[0] << endl;

const Pointer cp = &a;
cout << *cp << endl;
cout << (cp + 1) << endl;
cout << (cp - 1) << endl;
cout << cp[0] << endl;

return ;
}

ENDS(test5)

int main() {
// 友元
// test1::main();

// 重载运算符
// test2::main();

// 1.数组对象 // test3
// 2.函数对象 // test4
// 3.指针对象 // test5
//test3::main();
// test4::main();
test5::main();

return 0;
}

vector

源码赏析

push_back

image-20220716165144366

_M_insert_aux

_M_insert_aux:为什么会拷贝两次因为它不仅兼容push_back()方法 也兼容insert() 方法

image-20220716173720604

2倍扩容法为什么是o(1)时间复杂度

image-20220716173555339

shared_ptr

内存泄漏

简单地说就是申请了一块内存空间,使用完毕后没有释放掉。

  1. new和malloc申请资源使用后,没有用delete和free释放
  2. 子类继承父类时,父类析构函数不是虚函数
  3. Windows句柄资源使用后没有释放

智能指针引用计数

image-20220717094720291

环形引用

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 <memory>

using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespac

// 环形引用
BEGINS(test2)


class A {

public :
A() {
cout << "defaulr constructor" << endl;
}

~A() {
cout << "destructor" << endl;
}
shared_ptr<A> p;

};


int main() {
shared_ptr<A> p = make_shared<A>();
shared_ptr<A> q = make_shared<A>();
p->p = q;
q->p = p;
p = nullptr;
q = nullptr;
cout << "end main" << endl;
return 0;
}

ENDS(test2)

int main() {
// test1::main();
test2::main();
return 0;
}

image-20220717104120717

image-20220717104133063

实现自己的—shared_ptr

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*************************************************************************
> File Name: 13.shared_ptr.cpp
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年07月16日 星期六 21时35分20秒
************************************************************************/

#include <iostream>
#include <memory>

using namespace std;


#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(test1)

class A {

public :
A() {
cout << "defaulr constructor" << endl;
}

~A() {
cout << "destructor" << endl;
}

};

int main() {

A *p = new A();
// 如果不delete就会出现内存泄漏
// 使用原生指针是方式方法 带*
delete p;

// shared_ptr<A> 等价于 A *p
// make_shared<A>() 等价于 new A();
shared_ptr<A> p1 = make_shared<A>();
cout << "p.use_count = " << p1.use_count() << endl;
shared_ptr<A> q = p1;
cout << "p1.use_count = " << p1.use_count() << endl;
cout << "q.use_count = " << q.use_count() << endl;
p1 = nullptr;
cout << "q.use_count = " << q.use_count() << endl;
q = nullptr;
cout << "end main" << endl;

return 0;
}

ENDS(test1)

BEGINS(test3)

class A {

public :
A() {
cout << "defaulr constructor" << endl;

}
int x, y;
~A() {
cout << "destructor" << endl;
}
shared_ptr<A> p;

};


class ptr_data {

public :
ptr_data(A *ptr, int *cnt = nullptr) : ptr(ptr), cnt(cnt) {
if(this->cnt == nullptr) {
this->cnt = new int(1);
}
}

void increase_one() {
*cnt += 1;
return ;
}

void decrease_one() {
*cnt -= 1;
if(*cnt == 0) delete ptr;
return ;
}
// 加上const 主要是提供给const类型去用也提供给非const
bool operator==(const ptr_data &p) const {
return p.ptr == this->ptr && p.cnt == this->cnt;
}
~ptr_data() {
decrease_one();
if(*cnt == 0) delete cnt;
}

A *ptr;
int *cnt;
};

class shared_ptr {

public :
shared_ptr(A *ptr) : p(ptr){}
shared_ptr(const shared_ptr &p) : p(p.p) {
// cnt 引用计数 +1
this->p.increase_one();
}
shared_ptr &operator=(const shared_ptr &obj) {
if(obj.p == p) return *this;
p.decrease_one();
p = obj.p;
p.increase_one();
return *this;
}
A *operator->() {return p.ptr; };
A &operator*() { return *(p.ptr); }
int use_count() { return *p.cnt; }
~shared_ptr() {
p.decrease_one();
}

private :
ptr_data p;
};

shared_ptr make_shared() {
return shared_ptr(new A());
}

ostream &operator<<(ostream &out, const A &p) {
out << "class A : " << p.x << ", " << p.y << endl;
return out;
}

int main() {
shared_ptr p = make_shared();
p->x = 3, p->y = 4;
cout << *p << endl;
cout << "p.use_count = " << p.use_count() << endl;
shared_ptr q = p;
cout << "p.use_count = " << p.use_count() << endl;
cout << "q.use_count = " << q.use_count() << endl;
p = nullptr;
cout << "q.use_count = " << q.use_count() << endl;
q = nullptr;
cout << "end main" << endl;

return 0;
}

ENDS(test3)

int main() {
// 正常 shared_ptr
test1::main();
cout << endl << " -------------------------------------- ";
// 自己实现的 shared_ptr
test3::main();
return 0;
}

代码合集

  • 智能指针
  • 环形引用
  • 自己的shared_ptr
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*************************************************************************
> File Name: 13.shared_ptr.cpp
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年07月16日 星期六 21时35分20秒
************************************************************************/

#include <iostream>
#include <memory>

using namespace std;


#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(test1)

class A {

public :
A() {
cout << "defaulr constructor" << endl;
}

~A() {
cout << "destructor" << endl;
}

};

int main() {

A *p = new A();
// 如果不delete就会出现内存泄漏
// 使用原生指针是方式方法 带*
delete p;

// shared_ptr<A> 等价于 A *p
// make_shared<A>() 等价于 new A();
shared_ptr<A> p1 = make_shared<A>();
cout << "p.use_count = " << p1.use_count() << endl;
shared_ptr<A> q = p1;
cout << "p1.use_count = " << p1.use_count() << endl;
cout << "q.use_count = " << q.use_count() << endl;
p1 = nullptr;
cout << "q.use_count = " << q.use_count() << endl;
q = nullptr;
cout << "end main" << endl;

return 0;
}

ENDS(test1)


// 环形引用
BEGINS(test2)


class A {

public :
A() {
cout << "defaulr constructor" << endl;
}

~A() {
cout << "destructor" << endl;
}
shared_ptr<A> p;

};


int main() {
shared_ptr<A> p = make_shared<A>();
shared_ptr<A> q = make_shared<A>();
p->p = q;
q->p = p;
p = nullptr;
q = nullptr;
cout << "end main" << endl;
return 0;
}

ENDS(test2)

BEGINS(test3)

class A {

public :
A() {
cout << "defaulr constructor" << endl;

}
int x, y;
~A() {
cout << "destructor" << endl;
}
shared_ptr<A> p;

};


class ptr_data {

public :
ptr_data(A *ptr, int *cnt = nullptr) : ptr(ptr), cnt(cnt) {
if(this->cnt == nullptr) {
this->cnt = new int(1);
}
}

void increase_one() {
*cnt += 1;
return ;
}

void decrease_one() {
*cnt -= 1;
if(*cnt == 0) delete ptr;
return ;
}
// 加上const 主要是提供给const类型去用也提供给非const
bool operator==(const ptr_data &p) const {
return p.ptr == this->ptr && p.cnt == this->cnt;
}
~ptr_data() {
if(*cnt == 0) delete cnt;
}

A *ptr;
int *cnt;
};

class shared_ptr {

public :
shared_ptr(A *ptr) : p(ptr){}
shared_ptr(const shared_ptr &p) : p(p.p) {
// cnt 引用计数 +1
this->p.increase_one();
}
shared_ptr &operator=(const shared_ptr &obj) {
if(obj.p == p) return *this;
p.decrease_one();
p = obj.p;
p.increase_one();
return *this;
}
A *operator->() {return p.ptr; };
A &operator*() { return *(p.ptr); }
int use_count() { return *p.cnt; }
~shared_ptr() {
p.decrease_one();
}

private :
ptr_data p;
};

shared_ptr make_shared() {
return shared_ptr(new A());
}

ostream &operator<<(ostream &out, const A &p) {
out << "class A : " << p.x << ", " << p.y << endl;
return out;
}

int main() {
shared_ptr p = make_shared();
p->x = 3, p->y = 4;
cout << *p << endl;
cout << "p.use_count = " << p.use_count() << endl;
shared_ptr q = p;
cout << "p.use_count = " << p.use_count() << endl;
cout << "q.use_count = " << q.use_count() << endl;
p = nullptr;
cout << "q.use_count = " << q.use_count() << endl;
q = nullptr;
cout << "end main" << endl;

return 0;
}

ENDS(test3)

int main() {
test1::main();
// test2::main();
cout << endl << " -------------------------------------- ";
test3::main();
return 0;
}

sort方法实现

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
/*************************************************************************
> File Name: 14.sort.cpp
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年07月17日 星期日 17时47分20秒
************************************************************************/

#include <iostream>
#include <stdlib.h>
#include <functional>
#include <time.h>
#include <algorithm>
using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(test1)

bool cmp1(int x, int y) {
return x > y;
}

class CMP {

public :
bool operator()(const int &a, const int &b) {
return a < b;
}

};

void output(int *first, int *last, const char *s) {
cout << s;
while(first != last) {
cout << *first << " ";
++first;
}
cout << endl;
return ;
}

int main() {
srand(time(NULL));
int arr[100], n = 10;
for(int i = 0; i < n; ++i) {
i && cout << " ";
arr[i] = rand() % 100;
cout << arr[i];
}
cout << endl;
sort(arr, arr + n);
output(arr, arr + n, "none : ");

sort(arr, arr + n, cmp1);
output(arr, arr + n, "cmp1 : ");

CMP cmp2;
sort(arr, arr + n, cmp2);
output(arr, arr + n, "Class cmp2 : ");

return 0;
}

ENDS(test1)

BEGINS(test2)


bool cmp1(int x, int y) {
return x > y;
}

class CMP {

public :
bool operator()(const int &a, const int &b) {
return a < b;
}

};


// 普通
void sort2(int *first, int *last, function<int(int, int)> cmp = less<int>()) {
if (first >= last) return ;
int *x = first, *y = last - 1, z = *first;
while(x < y) {
while(x < y && cmp(z, *y)) --y;
if(x < y) *(x++) = *y;
while(x < y && cmp(*x, z)) ++x;
if(x < y) *(y--) = *x;
}
*x = z;
sort2(first, x, cmp);
sort2(x + 1, last, cmp);
return ;
}

const int threshold = 16;

// 单边递归法-无监督
void intor_loop(int *first, int *last, function<int(int ,int)> cmp = less<int>()) {
while(last - first > threshold) {
int *x = first, *y = last - 1, z = *first;
do {
while(cmp(*x, z)) ++x;
while(cmp(z, *y)) --y;
if(x <= y) {
swap(*x, *y);
++x, --y;
}
} while(x <= y);
intor_loop(x, last, cmp);
last = y + 1;
}
return ;
}

// 单边递归法-无监督
void sort1(int *first, int *last, function<int(int ,int)> cmp = less<int>()) {
while(first < last) {
int *x = first, *y = last - 1, z = *first;
do {
while(cmp(*x, z)) ++x;
while(cmp(z, *y)) --y;
if(x <= y) {
swap(*x, *y);
++x, --y;
}
} while(x <= y);
sort1(x, last, cmp);
last = y + 1;
}
return ;
}



void insertion_sort(int *first, int *last,function<int(int, int)> cmp = less<int>()) {
int *ind = first;
for(int *x = first + 1; x < last; ++x) {
if(cmp(*x, *ind)) ind = x;
}

while(ind != first) {
swap(*ind, *(ind - 1));
ind--;
}

for(int *x = first + 2; x < last; ++x) {
int *j = x;
while(cmp(*j, *(j -1))) {
swap(*j, *(j - 1));
--j;
}
}

return ;
}
void sort(int *first, int *last,function<int(int, int)> cmp = less<int>()) {
intor_loop(first, last, cmp);
insertion_sort(first, last, cmp);
return ;
}

void output(int *first, int *last, const char *s) {
cout << s;
while(first != last) {
cout << *first << " ";
++first;
}
cout << endl;
return ;
}

int main() {
srand(time(NULL));
int arr[100], n = 10;
for(int i = 0; i < n; ++i) {
i && cout << " ";
arr[i] = rand() % 100;
cout << arr[i];
}
cout << endl;
sort(arr, arr + n);
output(arr, arr + n, "none : ");

sort(arr, arr + n, cmp1);
output(arr, arr + n, "cmp1 : ");

CMP cmp2;
sort(arr, arr + n, cmp2);
output(arr, arr + n, "Class cmp2 : ");

return 0;
}

ENDS(test2)

BEGINS(test3)

using namespace test2;

int main() {
srand(time(NULL));
int arr[100], n = 10;
for(int i = 0; i < n; ++i) {
i && cout << " ";
arr[i] = rand() % 100;
cout << arr[i];
}
cout << endl;
sort1(arr, arr + n);
output(arr, arr + n, "none : ");

sort1(arr, arr + n, cmp1);
output(arr, arr + n, "cmp1 : ");

CMP cmp2;
sort1(arr, arr + n, cmp2);
output(arr, arr + n, "Class cmp2 : ");

return 0;
}

ENDS(test3)

// 基于迭代器的Sort
BEGINS(test4)


bool cmp1(int x, int y) {
return x > y;
}

class CMP {

public :
bool operator()(const int &a, const int &b) {
return a < b;
}

};

const int threshold = 16;

class RandomIter {

public :
RandomIter(int *ptr) : ptr(ptr) {}
int &operator*() { return *ptr; }
RandomIter operator-(int x) {return RandomIter(ptr - x); }
RandomIter operator+(int x) {return RandomIter(ptr + x); }
int operator-(const RandomIter &iter) { return ptr - iter.ptr; }
RandomIter &operator++() { ++ptr; return *this; }
RandomIter &operator--() { --ptr; return *this; }
bool operator <(const RandomIter &iter) const {
return ptr < iter.ptr;
}

bool operator>(const RandomIter &iter) const {
return iter < *this;
}

bool operator<=(const RandomIter &iter) {
return !(iter < *this);
}

bool operator>=(const RandomIter &iter) {
return !(*this < iter);
}

bool operator==(const RandomIter &iter) {
return !(*this < iter) && !(iter < *this);
}

bool operator!=(const RandomIter &iter) {
return !(*this == iter);
}

private :
int *ptr;
};


// 单边递归法-无监督
void intor_loop(RandomIter first, RandomIter last, function<bool(int ,int)> cmp = less<int>()) {
while(last - first > threshold) {
RandomIter x = first, y = last - 1;
int z = *first;
do {
while(cmp(*x, z)) ++x;
while(cmp(z, *y)) --y;
if(x <= y) {
swap(*x, *y);
++x, --y;
}
} while(x <= y);
intor_loop(x, last, cmp);
last = y + 1;
}
return ;
}

void insertion_sort(RandomIter first, RandomIter last,function<int(int, int)> cmp = less<int>()) {
RandomIter ind = first;
for(RandomIter x = first + 1; x < last; ++x) {
if(cmp(*x, *ind)) ind = x;
}

while(ind != first) {
swap(*ind, *(ind - 1));
--ind;
}

for(RandomIter x = first + 2; x < last; ++x) {
RandomIter j = x;
while(cmp(*j, *(j -1))) {
swap(*j, *(j - 1));
--j;
}
}

return ;
}
void sort(RandomIter first, RandomIter last,function<int(int, int)> cmp = less<int>()) {
intor_loop(first, last, cmp);
insertion_sort(first, last, cmp);
return ;
}

void output(int *first, int *last, const char *s) {
cout << s;
while(first != last) {
cout << *first << " ";
++first;
}
cout << endl;
return ;
}

int main() {
srand(time(NULL));
int arr[100], n = 10;
for(int i = 0; i < n; ++i) {
i && cout << " ";
arr[i] = rand() % 100;
cout << arr[i];
}
cout << endl;
sort(arr, arr + n);
output(arr, arr + n, "none : ");

sort(arr, arr + n, cmp1);
output(arr, arr + n, "cmp1 : ");

CMP cmp2;
sort(arr, arr + n, cmp2);
output(arr, arr + n, "Class cmp2 : ");

return 0;
}

ENDS(test4)

int main() {

test1::main();
cout << " ---------------- 分割线 ------------------ " << endl;

test2::main();
cout << " ---------------- 分割线 ------------------ " << endl;
test3::main();

cout << " ---------------- 分割线 ------------------ " << endl;
test4::main();
return 0;
}

源码文件*.cpp

点我跳转:https://github.com/qzwl123/C-/tree/main/%E5%B0%81%E8%A3%85

评论