#include <iostream>
#include <memory>
#include <vector>
using namespace std;
/*
1.shared_ptr允许多个指针指向同一个对象。
2.shared_ptr定义在memory头文件中。
3.默认初始化的智能指针中保存着一个空指针。
4.智能指针的使用方式与普通指针类似,解引用一个智能指针返回它指向的对象,是对象,而不是一个指针。
5.最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准函数,
此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。
6.调用make_shared在定义在memory文件当中。
7.调用make_shared<string>时,传递的参数必须与string的某个构造函数相匹配,
调用make_shared<int>时传递的参数必须能用来初始化一个int,以此类推。
如果我们不传递任何参数,对象就会进行值初始化。
8.通常用auto定义一个对象来保存make_shared的结果
9.若p.unique()为1,返回true,否则返回false。
10.当进行拷贝或赋值操作时,每隔shared_ptr都会记录有多少个其他shared_ptr指向相同的对象,
可以认为每个shared_ptr都有一个关联的计数器,通常称其为引用计数,无论何时我们拷贝一个shared_ptr,
计数器都会递增。
11.r = q,q的引用计数增加,r的引用计数先递减,然后指向q指向的对象,r的引用计数加1。
12.shared_ptr析构函数会递减它所指向的引用计数。如果引用计数变为0,shared_ptr的析构函数就会销毁对象,
并释放它的内存。
13.接受指针参数的智能指针构造函数是explicit的,因此我们不能将一个内置指针隐式转换为一个智能指针,
必须使用直接初始化形式来初始化一个智能指针。
14.不能进行内置指针到智能指针的隐式转换。
15.默认情况下,一个用来初始化智能指针的普通指针必须指向动态内存,因为智能指针默认使用delete释放它所关联的对象。
16.不要使用get初始化另一个智能指针或为智能指针赋值
17.使用get返回的指针的代码不能delete此指针
18.shared_ptr没有release函数
*/
class Student
{
public:
Student() {
cout << "调用Student的默认构造函数 name:" << m_name << endl;
}
Student(string name) : m_name(name) {
cout << "调用Student的自定义构造函数 name:" << m_name << endl;
}
Student(const Student &s) : m_name(s.m_name) {
cout << "调用Student的拷贝构造函数 name:" << m_name << endl;
}
~Student() {
cout << "调用Student的析构函数 name:" << m_name << endl;
}
string m_name;
int a;
};
auto deleter = [](Student *s) {
std::cout << "deleter name:" << s->m_name << endl;
};
void test(shared_ptr<Student> s)
{
cout << "func:" << __func__
<< " line:" << __LINE__
<< " s:" << s
<< " s.use_count:"
<< s.use_count()
<< endl;
if (s.unique()) {
std::cout << "s is unique" << endl;
} else {
std::cout << "s is not unique" << endl;
}
}
void test_local(Student s) {
cout << "func:" << __func__ << " line:" << __LINE__ << endl;
s.m_name = "许攸";
}
// 传给函数一个临时的shared_ptr,很可能导致错误
void test_01()
{
// test_local的实参是一个Student类的对象,接收郭嘉的是test_local函数的形参
// 当执行到test_local函数内部时,对象郭嘉没有被销毁,直到test_local执行完后,
// Student对象才会被销毁
// 郭嘉的生命周期在test_local函数中
test_local(Student("郭嘉"));
Student *s = new Student("燕青");
/*
* 合法,但是s所指向的内存会被释放
* 因为用普通指针s初始化一个智能指针,智能指针所指内存和普通指针s所指向内存相同
* 此智能指针创建后,test函数的形参接收Student的智能指针
* 当test函数调用过后,智能指针将会引用计数减一,当引用计数为0时,释放所指内存
* test执行完成后,s指针指向的内存释放,但是s还是指向原来的内存空间
*/
// 形参接收实参创建的智能指针
test(shared_ptr<Student> (s));
if (s) {
cout << "s is not nullptr 但s所指向的内存已经被释放了" << endl;
} else {
cout << "s is nullptr" << endl;
}
cout << __func__ << "函数结束" << endl;
}
// unique
void test_02()
{
shared_ptr<Student> s1 = make_shared<Student>("卫青");
if (s1.unique()) {
std::cout << "a1 is unique" << endl;
} else {
std::cout << "a1 is not unique" << endl;
}
std::cout << endl;
shared_ptr<Student> s2 = s1;
if (s2.unique()) {
std::cout << "s2 is unique" << endl;
} else {
std::cout << "s2 is not unique use_count:" << s2.use_count() << endl;
}
cout << "s1.name:" << s1->m_name << endl;
cout << "s2.name:" << s2->m_name << endl;
cout << "s1:" << s2 << " s2:" << s2 << endl;
cout << __func__ << "函数结束" << endl;
}
// 添加删除器
void test_03()
{
shared_ptr<Student> s1(new Student("步惊云"), deleter);
cout << "s1:" << s1 << endl;
/*
* error:
* no matching function for call to
* 'std::__cxx11::basic_string<char>::basic_string(std::__cxx11::basic_string<char>*, main()::<lambda(std::__cxx11::string*)>&)'
* { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
*/
// make_shared不允许自定义删除器
// shared_ptr<Student> s2 = make_shared<Student>(new Student("步惊云"), deleter);
// 添加删除器
s1.reset(new Student("步天"), deleter);
cout << "s1.name:" << s1->m_name << " s1:" << s1 << endl;
cout << __func__ << "函数结束" << endl;
}
// shared_ptr的use_count
void test_04()
{
// Student("朱重八")当做make_shared的参数,是局部变量,make_shared执行完后,Student("朱重八")要被释放掉
shared_ptr<Student> s1 = make_shared<Student>(Student("朱重八"));
cout << "s1.name:" << s1->m_name << endl;
shared_ptr<Student> s2 = make_shared<Student>(Student("朱标"));
cout << "s2.name:" << s2->m_name << endl;
// use_count的效率很低,仅用于调试
cout << "s1.use_count:" << s1.use_count() << endl;
cout << "s2.use_count:" << s2.use_count() << endl;
s1 = s2;
cout << "s1.use_count:" << s1.use_count() << endl;
cout << "s2.use_count:" << s2.use_count() << endl;
cout << __func__ << "函数结束" << endl;
}
shared_ptr<Student> FuncCreateStudent(Student *s)
{
cout << "func:" << __func__
<< " line:" << __LINE__ << endl;
auto s1 = make_shared<Student>(*s);
// 智能指针和智能指针内保存的普通指针指向的地址不同
cout << "s1.get:" << s1.get()
<< " s1:" << s1
<< " s:" << s
<< endl;
// 智能指针和智能指针包含的普通指针,两个指针的地址不同
auto p = s1.get();
cout << "&s1.get:" << &p
<< " &s1:" << &s1
<< endl;
/*
* 执行完make_shared<Student>(*s);后,因为没有定义变量接受make_shared返回的临时智能指针,
* 所以智能指针销毁
*/
// 这里是深拷贝,不是浅拷贝,所有普通指针s所指向的内存没有被释放
make_shared<Student>(*s);
std::cout << "func:" << __func__
<< " line:" << __LINE__
<< " s.name:" << s->m_name
<< endl;
// 尚可喜return后不释放,返回到调用函数当中继续使用
return make_shared<Student>("尚可喜");
}
void test_05()
{
auto s1 = new Student("吴应熊");
auto s2 = FuncCreateStudent(s1);
std::cout << "s1->m_name:" << s1->m_name
<< " s2->m_name:" << s2->m_name
<< endl;
std::cout << "s2.use_count:" << s2.use_count() << endl;
cout << __func__ << "函数结束" << endl;
}
void test_06()
{
Student *s1 = new Student("鳌拜");
auto s2 = make_shared<Student>(*s1);
auto s3 = new Student("索尼");
make_shared<Student>(*(s3));
/*make_shared返回的结果没有赋值给智能指针,
那么make_shared创建的智能指针就结束了生命周期,会调用析构函数释放内存 */
make_shared<Student>("苏克萨哈");
cout << __func__ << "函数结束" << endl;
}
// 判断智能指针是否为空
void test_07()
{
// 默认初始化的智能指针中保存着一个空指针。
shared_ptr<Student> s1;
if (s1) {
cout << "s1 is not nullptr" << endl;
} else {
cout << "s1 is nullptr" << endl;
}
shared_ptr<string> str;
cout << "func:" << __func__ << " line:" << __LINE__ << endl;
// str包含的指针为空,空指针调用empty函数崩溃
// if (str->empty()) {
// cout << "str->empty is empty " << endl;
// }
cout << "func:" << __func__ << " line:" << __LINE__ << endl;
shared_ptr<Student> s2 = make_shared<Student>("遏必隆");
// s1->m_name等价于(*s1).m_name
// s1.get()返回s1中保存的指针
cout << __func__ << "函数结束" << endl;
}
void test_08()
{
Student *s1 = new Student("多隆");
cout << "s1->m_name:" << s1->m_name << " s1:" << s1 << endl;
{
// 这种方式创建的shared_ptr<Student>指针所指内存地址和s1所指内存地址是一样的
shared_ptr<Student> s2(s1);
Student *s3 = s2.get();
cout << "s2->m_name:" << s2->m_name << " s2->use_count:" << s2.use_count() << endl;
cout << "s1:" << s1 << " s2:" << s2 << " s3:" << s3 << endl;
cout << endl;
}
// a1所指的内存已经被释放,所有不能访问a1的成员变量
// cout << "s1->m_name:" << s1->m_name << endl;
Student *s4 = new Student("豪格");
cout << "s4->m_name:" << s4->m_name << " s4:" << s4 << endl;
{
auto s5 = make_shared<Student>(*s4);
cout << "s5->m_name:" << s5->m_name
<< " s5->use_count:" << s5.use_count()
<< endl;
cout << endl;
}
cout << "s1->m_name:" << s1->m_name << " s1:" << s1 << endl;
cout << __func__ << "函数结束" << endl;
}
// 智能指针解引用
void test_09()
{
shared_ptr<int> p1(new int(10));
shared_ptr<int> p2 = make_shared<int>(10);
cout << "*p1:" << *p1 << endl;
cout << "*p2:" << *p2 << endl;
cout << __func__ << "函数结束" << endl;
}
void test_10()
{
// 调用自定义构造函数
Student *s1 = new Student("岱宗");
shared_ptr<Student> s2(s1);
// 调用自定义构造函数
shared_ptr<Student> s3 = make_shared<Student>("宋江");
shared_ptr<Student> s4(s3);
cout << __func__ << "函数结束" << endl;
}
void test_11()
{
unique_ptr<int> q(new int(10));
// error:书上说这样可以,但是代码里面不行
// shared_ptr<int> p1(q);
cout << __func__ << "函数结束" << endl;
}
void test_12()
{
shared_ptr<Student> s1 = make_shared<Student>("甘宁");
cout << "s1:" << s1 << endl;
// 在test函数形参的引用计数为2,s1和形参指向同一块内存
test(s1);
cout << __func__ << "函数结束" << endl;
}
void test_13()
{
shared_ptr<Student> s1 = make_shared<Student>("s1");
Student *s2 = s1.get();
// 错误:使用get返回的指针不能使用delete释放
delete s2;
s2 = nullptr;
cout << __func__ << "函数结束" << endl;
}
void test_14()
{
shared_ptr<Student> s1 = make_shared<Student>("甘兴霸");
// 先创建
s1.reset(new Student("孙策"));
cout << "s1.name:" << s1->m_name << endl;
cout << __func__ << "函数结束" << endl;
}
void test_15()
{
// 默认初始化的智能指针不调用构造函数,智能指针s1为空,智能指针中保存空指针
shared_ptr<Student> s1;
if (s1) {
cout << "s1不为空" << endl;
} else {
cout << "s1为空" << endl;
}
shared_ptr<Student> s2 = make_shared<Student>("张飞");
if (s2) {
cout << "s2不为空 name:" << s2->m_name << endl;
} else {
cout << "s2为空" << endl;
}
// 智能指针s3不为空
shared_ptr<Student> s3 = make_shared<Student>();
if (s3) {
cout << "s3不为空 name:" << s3->m_name << endl;
} else {
cout << "s3为空" << endl;
}
}
void test_16(vector<shared_ptr<Student>> &vec)
{
auto s1 = make_shared<Student>("张飞");
auto s2 = make_shared<Student>("刘备");
auto s3 = make_shared<Student>("关羽");
cout << "s1.a:" << s1->a << endl;
vec.push_back(s1);
vec.push_back(s2);
vec.push_back(s3);
cout << "s1.use_count:" << s1.use_count() << endl;
cout << "s2.use_count:" << s2.use_count() << endl;
cout << "s3.use_count:" << s3.use_count() << endl;
}
void test_17(vector<shared_ptr<Student>> &vec)
{
for (size_t i = 0; i < vec.size(); i++) {
cout << "func:" << __func__
<< " line:" << __LINE__
<< "name:" << vec[i]->m_name
<< " use_count:" << vec[i].use_count()
<< endl;
}
for (auto v : vec) {
cout << "v.name:" << v->m_name
<< " use_count:" << v.use_count()
<< endl;
}
for (size_t i = 0; i < vec.size(); i++) {
cout << "func:" << __func__
<< " line:" << __LINE__
<< "name:" << vec[i]->m_name
<< " use_count:" << vec[i].use_count()
<< endl;
}
// 容器内的shared_ptr只有调用erase,才会引用计数减一
for (auto it = vec.begin(); it != vec.end();) {
it = vec.erase(it);
}
cout << "func:" << __func__ << " 结束" << endl;
}
void test_18()
{
shared_ptr<Student> s1 = make_shared<Student>("孙悟空");
// shared_ptr没有release函数
// s1.release();
}
void test_19()
{
shared_ptr<Student> sp1 = make_shared<Student>("孙悟空");
shared_ptr<Student> sp2 = sp1;
cout << "sp1.use_count:" << sp1.use_count()
<< " sp2.use_count:" << sp2.use_count()
<< endl;
// 调用reset将sp1的引用计数减一
sp1.reset();
cout << "sp1.use_count:" << sp1.use_count()
<< " sp2.use_count:" << sp2.use_count()
<< endl;
sp2.reset();
cout << "func:" << __func__ << " 结束" << endl;
}
// 动态分配的const对象
void test_20()
{
const int *pi1 = new int();
cout << "*pi1:" << *pi1 << endl;
pi1 = new int(11);
cout << "*pi1:" << *pi1 << endl;
cout << "func:" << __func__ << " 结束" << endl;
}
int main()
{
system("chcp 65001");
// test_00();
// test_01();
// test_02();
// test_03();
// test_04();
// test_05();
// test_06();
// test_07();
// test_08();
// test_09();
// test_10();
// test_11();
// test_12();
// test_13();
// test_14();
vector<shared_ptr<Student>> vec;
// test_16(vec);
// test_17(vec);
// test_18();
// test_19();
test_20();
return 0;
}
shared_ptr总结
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 注 make_shared & shared_ptr make_shared 和 shared_ptr 的用处 通...
- 有使用 C++ 做开发的童鞋应该都经历过被 指针 折磨,使用指针的使用需要保证 new 和 delete 对齐,如...