C++ 补充 & C++ 11 - C++智能指针shared_ptr 使用详解 (C++11)

shared_ptr 使用详解 (C++11)

熟悉了unique_ptr 后,其实我们发现unique_ptr 这种排他型的内存管理并不能适应所有情况,有很大的局限!如果需要多个指针变量共享怎么办?

如果有一种方式,可以记录引用特定内存对象的智能指针数量,当复制或拷贝时,引用计数加1,当智能指针析构时,引用计数减1,如果计数为零,代表已经没有指针指向这块内存,那么我们就释放它!这就是 shared_ptr 采用的策略!

在这里插入图片描述

构造函数

shared_ptr sp ; //空的shared_ptr,可以指向类型为T的对象
shared_ptr sp1(new T()) ;//定义shared_ptr,同时指向类型为T的对象
shared_ptr<T[]> sp2 ; //空的shared_ptr,可以指向类型为T[的数组对象 C++17后支持
shared_ptr<T[]> sp3(new T[]{…}) ;//指向类型为T的数组对象 C++17后支持
shared_ptr sp4(NULL, D()); //空的shared_ptr,接受一个D类型的删除器,使用D
释放内存
shared_ptr sp5(new T(), D()); //定义shared_ptr,指向类型为T的对象,接受一个D 类型的删除器,使用D删除器来释放内存

初始化

方式一 构造函数
shared_ptrr up1(new int(10)); //int(10) 的引用计数为1
shared_ptrr up2(up1); //使用智能指针up1构造up2, 此时int(10) 引用计数为2

方式二 使用make_shared 初始化对象,分配内存效率更高
make_shared函数的主要功能是在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr; 用法:
make_shared<类型>(构造类型对象需要的参数列表);
shared_ptr p4 = make_shared(2); //多个参数以逗号’,'隔开,最多接受十个
shared_ptr p4 = make_shared(“字符串”);

demo 代码(一)

#include <iostream>
#include <stdio.h>
#include <memory>

using namespace std;

class Person
{
public:
	Person(int v)
	{
		this->no = v;
		cout << "Construct" << no << endl;
	}

	~Person()
	{
		cout << "Destruct" << no << endl;
	}
	
private:
	int no;

};

int main(void)
{
	shared_ptr<Person> sp1; /* 空的shared_ptr, 可以指向类型为T的对象 */
	shared_ptr<Person> sp2(new Person(2)); /* 定义shared_ptr, 同时指向类型为T的对象 */

	cout << "sp1 ref_counter: " << sp1.use_count() << endl;
	cout << "sp2 ref_counter: " << sp2.use_count() << endl; /* 当前管控Person(2) 的共享指针的数量 */

	sp1 = sp2;
	cout << "after sp1 = sp2, sp2 ref_counter: " << sp2.use_count() << endl;

	shared_ptr<Person> sp3(sp1);
	cout << "after sp3(sp1), sp2 ref_counter: " << sp2.use_count() << endl;

	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

demo 代码(二)

#include <iostream>
#include <stdio.h>
#include <memory>

using namespace std;

class Person
{
public:
	Person(int v)
	{
		this->no = v;
		cout << "Construct" << no << endl;
	}

	~Person()
	{
		cout << "Destruct" << no << endl;
	}
	
private:
	int no;

};

int main(void)
{
	shared_ptr<Person> sp1; /* 空的shared_ptr, 可以指向类型为T的对象 */
	shared_ptr<Person> sp2(new Person(2)); /* 定义shared_ptr, 同时指向类型为T的对象 */

	cout << "sp1 ref_counter: " << sp1.use_count() << endl;
	cout << "sp2 ref_counter: " << sp2.use_count() << endl; /* 当前管控Person(2) 的共享指针的数量 */

	sp1 = sp2;
	cout << "after sp1 = sp2, sp2 ref_counter: " << sp2.use_count() << endl;

	shared_ptr<Person> sp3(sp1);
	cout << "after sp3(sp1), sp2 ref_counter: " << sp2.use_count() << endl;

	/* 数组对象的管理 */
	shared_ptr<Person[]> sp4(new Person[5]{ 3,4,5,6,7 }); /* delete [] */

	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

demo 代码(三)

#include <iostream>
#include <stdio.h>
#include <memory>

using namespace std;

class Person
{
public:
	Person(int v)
	{
		this->no = v;
		cout << "Construct" << no << endl;
	}

	~Person()
	{
		cout << "Destruct" << no << endl;
	}
	
private:
	int no;

};

class DestructPerson
{
public:
	void operator()(Person* pt)
	{
		cout << "DestructPerson" << endl;
		delete pt;
	}
};


int main(void)
{
	shared_ptr<Person> sp1; /* 空的shared_ptr, 可以指向类型为T的对象 */
	shared_ptr<Person> sp2(new Person(2)); /* 定义shared_ptr, 同时指向类型为T的对象 */

	cout << "sp1 ref_counter: " << sp1.use_count() << endl;
	cout << "sp2 ref_counter: " << sp2.use_count() << endl; /* 当前管控Person(2) 的共享指针的数量 */

	sp1 = sp2;
	cout << "after sp1 = sp2, sp2 ref_counter: " << sp2.use_count() << endl;

	shared_ptr<Person> sp3(sp1);
	cout << "after sp3(sp1), sp2 ref_counter: " << sp2.use_count() << endl;

	/* 数组对象的管理 */
	shared_ptr<Person[]> sp4(new Person[5]{ 3,4,5,6,7 }); /* delete [] */

	shared_ptr<Person> sp8(new Person(8), DestructPerson()); /* 调用 DestructPerson 释放对象 */

	/* 使用 make_shared 函数模板初始化 */
	shared_ptr<Person> sp9;
	sp9 = make_shared<Person>(9);
	cout << "after sp9 = mke_shared<Person>(9), sp9 ref_counter: " << sp9.use_count() << endl;

	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

demo 代码(四)

#include <iostream>
#include <stdio.h>
#include <memory>

using namespace std;

class Person
{
public:
	Person(int v)
	{
		this->no = v;
		cout << "Construct" << no << endl;
	}

	~Person()
	{
		cout << "Destruct" << no << endl;
	}
	
private:
	int no;

};

class DestructPerson
{
public:
	void operator()(Person* pt)
	{
		cout << "DestructPerson" << endl;
		delete pt;
	}
};


int main(void)
{
	shared_ptr<Person> sp1; /* 空的shared_ptr, 可以指向类型为T的对象 */
	shared_ptr<Person> sp2(new Person(2)); /* 定义shared_ptr, 同时指向类型为T的对象 */

	cout << "sp1 ref_counter: " << sp1.use_count() << endl;
	cout << "sp2 ref_counter: " << sp2.use_count() << endl; /* 当前管控Person(2) 的共享指针的数量 */

	sp1 = sp2;
	cout << "after sp1 = sp2, sp2 ref_counter: " << sp2.use_count() << endl;

	shared_ptr<Person> sp3(sp1);
	cout << "after sp3(sp1), sp2 ref_counter: " << sp2.use_count() << endl;

	/* 数组对象的管理 */
	shared_ptr<Person[]> sp4(new Person[5]{ 3,4,5,6,7 }); /* delete [] */

	shared_ptr<Person> sp8(new Person(8), DestructPerson()); /* 调用 DestructPerson 释放对象 */

	/* 使用 make_shared 函数模板初始化 */
	shared_ptr<Person> sp9;
	sp9 = make_shared<Person>(9);
	cout << "after sp9 = mke_shared<Person>(9), sp9 ref_counter: " << sp9.use_count() << endl;

	shared_ptr<Person> sp10;
	Person* p10 = new Person(10);
	sp9.reset(p10);
	cout << "after sp9.reset(p10), sp9 ref_counter: " << sp9.use_count() << endl;


	system("pause");
	return 0;
}

执行:

在这里插入图片描述

demo 代码(五)

#include <iostream>
#include <stdio.h>
#include <memory>

using namespace std;

class Person
{
public:
	Person(int v)
	{
		this->no = v;
		cout << "Construct" << no << endl;
	}

	~Person()
	{
		cout << "Destruct" << no << endl;
	}

	int no;

};

class DestructPerson
{
public:
	void operator()(Person* pt)
	{
		cout << "DestructPerson" << endl;
		delete pt;
	}
};


int main(void)
{
	shared_ptr<Person> sp1; /* 空的shared_ptr, 可以指向类型为T的对象 */
	shared_ptr<Person> sp2(new Person(2)); /* 定义shared_ptr, 同时指向类型为T的对象 */

	cout << "sp1 ref_counter: " << sp1.use_count() << endl;
	cout << "sp2 ref_counter: " << sp2.use_count() << endl; /* 当前管控Person(2) 的共享指针的数量 */

	sp1 = sp2;
	cout << "after sp1 = sp2, sp2 ref_counter: " << sp2.use_count() << endl;

	shared_ptr<Person> sp3(sp1);
	cout << "after sp3(sp1), sp2 ref_counter: " << sp2.use_count() << endl;

	/* 数组对象的管理 */
	shared_ptr<Person[]> sp4(new Person[5]{ 3,4,5,6,7 }); /* delete [] */

	shared_ptr<Person> sp8(new Person(8), DestructPerson()); /* 调用 DestructPerson 释放对象 */

	/* 使用 make_shared 函数模板初始化 */
	shared_ptr<Person> sp9;
	sp9 = make_shared<Person>(9);
	cout << "after sp9 = mke_shared<Person>(9), sp9 ref_counter: " << sp9.use_count() << endl;

	shared_ptr<Person> sp10 = sp9;
	Person* p10 = new Person(10);
	sp9.reset(p10);
	cout << "after sp9.reset(p10), sp9 ref_counter: " << sp9.use_count() << endl;

	/* 交换 swap 用法 */
	std::swap(sp9, sp10);

	cout << "交换后, sp9: " << sp9->no << "sp10: " << sp10->no << endl;

	sp9.swap(sp10);
	cout << "sp9. swap(sp10) 交换后, sp9: " << sp9->no << " sp10: " << sp10->no << endl;

	system("pause");
	return 0;
}

运行结果:

在这里插入图片描述

赋值

shared_ptrr up1(new int(10)); //int(10) 的引用计数为1
shared_ptr up2(new int(11)); //int(11) 的引用计数为1
up1 = up2;//int(10) 的引用计数减1,计数归零内存释放,up2共享int(11)给up1, int(11)
的引用计数为2

主动释放对象

shared_ptrr up1(new int(10));
up1 = nullptr ;//int(10) 的引用计数减1,计数归零内存释放

up1 = NULL; //作用同上

重置

up.reset() ; //将p重置为空指针,所管理对象引用计数 减1
up.reset(p1); //将p重置为p1(的值),p 管控的对象计数减1,p接管对p1指针的管控
up.reset(p1,d); //将p重置为p(的值),p 管控的对象计数减1并使用d作为删除器

交换

std::swap(p1,p2); //交换p1 和p2 管理的对象,原对象的引用计数不变
p1.swap(p2); //同上

使用陷阱

shared_ptr作为被管控的对象的成员时,小心因循环引用造成无法释放资源!

#include <stdio.h>
#include <iostream>
#include <string>
#include <memory>
#include <vector>

using namespace std;

class girl;

class boy
{
public:
	boy()
	{
		cout << "boy construct!" << endl;
	}

	~boy()
	{
		cout << "boy destruct!" << endl;
	}

	void set_girl_friend(shared_ptr<girl>& g)
	{
		this->girl_friend = g;
	}

private:
	shared_ptr<girl> girl_friend;
};

class girl
{
public:
	girl()
	{
		cout << "girl construct !" << endl;
	}

	~girl()
	{
		cout << "girl destruct!" << endl;
	}

	void set_boy_friend(shared_ptr<boy>& b)
	{
		this->boy_friend = b;
	}

private:
	shared_ptr<boy> boy_friend;
};

void use_trap()
{
	shared_ptr<girl> sp_girl(new girl()); /* 白娘子 */
	shared_ptr<boy> sp_boy(new boy()); /* 许仙 */

	sp_girl->set_boy_friend(sp_boy);
	sp_boy->set_girl_friend(sp_girl);

}


int main()
{
	use_trap();

	system("pause");
	return 0;
}

结语:

这时间, 快高考了!!!

时间: 2020-07-03

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章