C++教程(4) C++标准库

Pair

Class Pair将两个value视为一个单元

1
2
3
4
5
6
7
8
namespace std{
template<typename T,typename U>
struct pair{
T first;
U second;
...
};
}

Tuple

tuple可拥有任意类型任意数量的元素

1
std::tuple<int, double, char,std::string> tuple(1, 2.3, 'y', "hello wolrd");


tuple不允许迭代,运行时传入索引值将报错
1
std::get<i>(tuple);//错误

Smart Pointer(智能指针)

Smart Pointer能够得知本身是否为指向某个对象的最后一个指针,当其为指向某个对象的最后一个指针且被删除时即会销毁所指对象

shared_ptr

共享式拥有 多个smart pointer指向同一对象,对象和资源在最后一个smart pointer销毁时被释放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
#include<string>
#include<vector>
#include<memory>
using namespace std;
int main() {
shared_ptr<string> x(new string("kyleson"));
shared_ptr<string> y(new string("monica"));
(*x)[0] = 'K';
y->replace(0, 1, "J");
vector<shared_ptr<string>> person;
person.push_back(x);
person.push_back(y);
person.push_back(x);
person.push_back(y);
for (auto ptr : person)
cout << *ptr << " ";
cout << endl;
*x = "Nonica";
for (auto ptr : person)
cout << *ptr << " ";
cout << endl;
cout << "use_count:" << person[0].use_count() << endl;//所指对象当前拥有者(指针)数量
getchar();
return 0;
}
Kyleson Jonica Kyleson Jonica
Nonica Jonica Nonica Jonica
use_count:3

当string的最后一个拥有者shared_ptr被销毁,所指对象随即调用delete
对象的delete不一定发生在 程序终点 , 将nullptr赋值给x或者调整vector大小使其只含有y,则都会调用delete

自定义delete

1
2
3
4
5
shared_ptr<string> x(new string("kyleson"), 
[](string *p){
cout << "delete" << *p;
delete p;
});

当最后一个拥有者被销毁时,将调用该lambda函数

shared point的默认调用delete,而非delete [],当智能指针指向数组时需自定义delete

1
2
shared_ptr<int> p(new int[10], [](int *p) {delete[] p; });
shared_ptr<int> p(new int[10],std::default_delete<int[]>());//利用unique_ptr提供的辅助函数

weak_ptr

weak_ptr共享但不拥有某对象,一旦最末拥有该对象的shared_ptr失去拥有权,任何weak_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
#include<iostream>
#include<string>
#include<vector>
#include<memory>
using namespace std;
class Person {
public:
string name;
shared_ptr<Person> mother;
shared_ptr<Person> father;
vector<shared_ptr<Person>> kids;
Person(const string &name,
shared_ptr<Person> m = nullptr,
shared_ptr<Person> f = nullptr) :
name(name), mother(m), father(f) {};
~Person(){
std::cout << "delete " << name << endl;
}
};
shared_ptr<Person> initFamily(const string &name) {
shared_ptr<Person> mom(new Person(name + "'s mom"));
shared_ptr<Person> dad(new Person(name + "'s dad"));
shared_ptr<Person> kid(new Person(name, mom, dad));
mom->kids.push_back(kid);
dad->kids.push_back(kid);
return kid;
}
int main() {
shared_ptr<Person> p = initFamily("kyleson");
cout << "kyleson's family exits" << endl;
cout << "- kyleson is shared " << p.use_count() << " times" << endl;
cout << "- name of 1st kid of kyleson's mom:"
<< p->mother->kids[0]->name << endl;
p = initFamily("Ninoca");
cout << "- Ninoca is shared " << p.use_count() << " times" << endl;
getchar();
return 0;
}
kyleson's family exits
- kyleson is shared 3 times
- name of 1st kid of kyleson's mom:kyleson
- Ninoca is shared 3 times

程序结束时,并未打印”delete kyleon”或“delete Ninoca”,即未执行析构函数,Person内部存在循环指向,其对象在程序结束时仍至少被一个shared_ptr指向.
1
2
3
4
5
6
7
8
9
10
11
12
vector<weak_ptr<Person>> kids;
cout << "- name of 1st kid of kyleson's mom:"
<< p->mother->kids[0].lock()->name << endl;

kyleson's family exits
- kyleson is shared 1 times
- name of 1st kid of kyleson's mom:kyleson
delete kyleson
delete kyleson's dad
delete kyleson's mom
- Ninoca is shared 1 times
...

使用weak_ptr将会解决循环指向问题,当改变p的指向后调用了析构函数,且当程序结束时”Ninoca”的析构函数也将被调用
1
2
3
4
int *x = new int;
shared_ptr<int> sp1(x);
shared_ptr<int> sp2(x);//错误
shared_ptr<int> sp3 = sp1;//正确

问题出在sp1和sp2意味着”两个指向团队”,都会在丢失x的拥有权时释放资源,因此相应的资源会被释放两次而导致错误
1
2
3
4
5
6
7
8
9
10
11
12
13
class Person {
public:
...
void setParentAndTheirKids(shared_ptr<Person> m = nullptr, shared_ptr<Person> f = nullptr) {
mother = m;
father = f;
if (m != nullptr)
m->kids.push_back(shared_ptr<Person>(this));//错误 引入了新的指向团队
if (f != nullptr)
f->kids.push_back(shared_ptr<Person>(this));//错误 引入了新的指向团队

}
};

根据this建立的shared_ptr同样建立了新的”指向团队”
1
2
3
4
5
6
7
8
9
10
11
12
class Person :std::enable_shared_from_this<Person>{
public:
...
void setParentAndTheirKids(shared_ptr<Person> m = nullptr, shared_ptr<Person> f = nullptr) {
mother = m;
father = f;
if (m != nullptr)
m->kids.push_back(shared_from_this());
if (f != nullptr)
f->kids.push_back(shared_from_this());
}
};

unique_ptr

独占式拥有 同一时间只有一个smart pointer指向该对象


C++教程(4) C++标准库
https://jiaopaner.github.io/2019/07/09/C++教程(4) C++标准库/
作者
JiaoPan
发布于
2019年7月9日
许可协议