c++ set容器存储指针,智能指针用法

1 篇文章 0 订阅

Set容器存储c++内置变量

set容器存储基础变量像int,char,或者是string对象,我们不需要去写比较函数,但是如果存储的是自定义类对象或者是结构体,那就需要重载<运算符或者重载(),在构造set容器时作为第二个参数传入,set容器存储内置变量,我就不记录了,这篇文章主要讲存储类对象以及用指针或者智能指针存储的用法

Set容器存储指向类对象的智能智能对象

我们知道stl存储对象时有一个特点,就是其实是对对象进行拷贝,然后存储,同时如果声明的是基类对象,而实际插入时是子类对象,那和子类相关的成员变量和函数就会被剥离,也就是不支持多态.所以我们一般选择存储指针,但是由于存储普通指针时,stl容器会对指针和指针指向的内存也进行拷贝,所以容器只会对它拷贝的那个指针变量指向的内存进行管理,而之前的内存需要我们自己去释放,所以使用智能指针就是最佳的选择.至于使用shared_ptr还是unique_ptr,这里需要根据自己需求来选,他们的区别,可以自己去了解,我只写使用shared_ptr的示例:

#include <iostream>
#include <set>
#include <memory>
#include <functional>
#include <unordered_set>
using namespace std;

namespace set_test
{
  struct song
  {
  	int m_id;
  	int m_hot;
  	song(int id, int hot)
  	{

  		this->m_id = id;
  		this->m_hot = hot;
  	}
  	~song() {
  		cout << "~song:m_id=" << m_id << ",m_hot=" << m_hot << endl;
  	}
  	//set容器中存放类对象时,自定义比较函数方式1:内部重载<
  	bool operator<(const struct song & right)const   //重载<运算符
  	{
  		if (this->m_id == right.m_id)     //根据id去重
  			return false;
  		else
  		{
  			if (this->m_hot != right.m_hot)
  			{
  				return this->m_hot > right.m_hot;      //降序
  			}
  			else
  			{
  				return this->m_id > right.m_id;
  			}
  		}
  	};

  	//set容器中存放类对象智能指针时,自定义比较函数方式1:friend方式重载<
  	friend	bool operator <(const shared_ptr< song>& left, const shared_ptr< song>&  right)
  	{
  		//return false;
  		if (left->m_id == right->m_id)     //根据id去重
  			return false;
  		else
  		{
  			if (left->m_hot != right->m_hot)
  			{
  				return left->m_hot < right->m_hot;      //降序
  			}
  			else
  			{
  				return left->m_id < right->m_id;
  			}

  		}
  	}
  };


  //set容器中存放类对象时,自定义比较函数方式2:指定set_comp为函数对象(必须申明为const引用)
  struct set_comp
  {
  	bool operator()(const struct song& left, const struct song&  right)  //重载()运算符
  	{

  		if (left.m_id == right.m_id)     //根据id去重
  			return false;
  		else
  		{
  			if (left.m_hot != right.m_hot)
  			{
  				return left.m_hot > right.m_hot;      //降序
  			}
  			else
  			{
  				return left.m_id > right.m_id;
  			}

  		}
  	}

  };

  //set容器中存放类对象智能指针时,自定义比较函数方式2:指定set_share_ptr_compptr为函数对象(必须申明为const引用)
  struct set_share_ptr_compptr
  {
  	bool operator()(const shared_ptr <song>& left, const shared_ptr<song>& right)  //重载()运算符
  	{
  		if (left->m_id == right->m_id)     //根据id去重
  			return false;
  		else
  		{
  			if (left->m_hot != right->m_hot)
  			{
  				return left->m_hot > right->m_hot;      //降序
  			}
  			else
  			{
  				return left->m_id > right->m_id;
  			}

  		}
  	}

  };

  void print_set(std::set<shared_ptr< song>>& prSet)
  {
  	for (auto& it : prSet)
  	{
  		std::cout << "id:" << it->m_id << ",hot:" << it->m_hot << endl;
  	}
  }

  //set存储类对象
  void test1()
  {
  	cout << "set存储类对象,使用类成员函数作为比较函数:" << endl;

  	std::set<song> mySet;     //使用重载的<
  	auto s1 = song(10, 100);
  	auto s2 = song(20, 200);
  	auto s3 = song(20, 300);//重复的插不进

  	auto s4 = song(40, 300);
  	auto s5 = song(50, 200);
  	auto s6 = song(60, 400);
  	auto s7 = song(50, 300);

  	mySet.insert(s1);    //插入s1
  	mySet.insert(s2);    //插入s2
  	mySet.insert(s3);    //s3和s2的id相同,不插入
  	mySet.insert(s4);    //插入s4
  	mySet.insert(s5);    //s5 m_hot比s4 m_hot小在s4后面
  	mySet.insert(s6);    //s6 m_hot比s4 m_hot大在s4前面
  	mySet.insert(s7);    //s7 m_hot和s4 一样大,但是s7 m_id比s4 m_id大,

  	cout << "set存储类对象,使用函数对象作为比较函数:" << endl;
  	std::set<song, set_comp> mySet1;    //使用外部定义的的()
  	for (auto&val : mySet)
  	{
  		mySet1.emplace(val);
  	}
  }

  //set存储智能指针
  void test2()
  {
  	cout << "set存储类对象智能指针,使用类成员函数作为比较函数:" << endl;
  	std::set<shared_ptr< song>> mySet;      //使用重载的<
  	auto s1 = std::make_shared<song>(10, 100);
  	auto s2 = std::make_shared<song>(20, 200);
  	auto s3 = std::make_shared<song>(20, 300);//重复的插不进
  	auto s4 = std::make_shared<song>(30, 300);
  	auto s5 = std::make_shared<song>(40, 200);
  	auto s6 = std::make_shared<song>(40, 200);//重复的插不进
  	auto s7 = std::make_shared<song>(50, 400);//重复的插不进

  	mySet.insert(s1);    //插入s1
  	mySet.insert(s2);    //插入s2
  	mySet.insert(s3);    //s3和s2的id相同,不插入
  	mySet.insert(s4);    //插入s4
  	mySet.insert(s5);    //插入s5,看和s4是如何排序的
  	mySet.insert(s6);    //看是否插的进
  	mySet.insert(s7);    //看是否插的进

  	//输出一次
  	print_set(mySet);

  	//修改一个值,再看输出
  	for (auto &info : mySet)
  	{
  		if (info->m_id == 10)
  		{
  			info->m_hot = 1000;
  			break;
  		}
  	}
  	cout << "修改后输出" << endl;

  	std::set<shared_ptr< song>> mySet1;      //使用重载的<
  	mySet.swap(mySet1);
  	//输出一次
  	print_set(mySet);
  	print_set(mySet1);

  	cout << "修改后再插入新值:" << endl;
  	mySet1.insert(std::make_shared<song>(60, 600));

  	print_set(mySet1);

  	/*
  	修改容器对象成员变量值,不会引起重新排序,即使插入新值也只是新值进行排序,被修改的值不会排序
  	*/


  	cout << "set存储类对象智能指针,使用函数对象作为比较函数:" << endl;
  	std::set<shared_ptr< song>, set_share_ptr_compptr> mySet2;    //使用外部定义的的()
  	for (auto&val : mySet1)
  	{
  		mySet2.emplace(val);
  	}
  }

  //测试遍历一个set删除另外一个set中的元素
  void test3()
  {
  	set < shared_ptr<song>> set1, set2;

  	for (int i = 0; i < 10; i++)
  	{
  		set1.insert(make_shared<song>(i, i * 10));
  	}
  	for (auto& str : set1)
  	{
  		set2.insert(str);
  	}

  	//删除第一个
  	set2.erase(*(set1.begin())); //用元素关键值删除
  	set2.erase(set2.begin());//用迭代器删除

  	//遍历set2,删除set1中的元素
  	for (auto it = set2.begin(); it != set2.end();)
  	{
  		set1.erase(*it);
  		if ((*it)->m_id != 9)
  		{
  			set2.erase(it++);//迭代器先加再删除
  			//it = set2.erase(it);//等价于上面那种写法
  		}
  		else
  		{
  			it++;
  		}
  	}

  	//因为自定义了比较函数,比较函数中当m_id相同时就可以判断是同一个元素,所以可以通过构建临时对象来删除;
  	set2.erase(make_shared<song>(9, 90));
  }

  void test_all()
  {
  	test1();
  	test2();
  	test3();
  };

}
  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值