迭代器(c++)、智能指针
一、迭代器
迭代器iterator是指针pointer的泛化,他允许程序员以相同的方式处理不同的数据结构(容器),提供了类似指针的操作(例如++、*、->运算符)或者说迭代器是一种检查容器的工具
不同容器的迭代器,其功能强弱有所不同,定义的操作不一样。常见的迭代器按功能强弱分为输入、输出、正向、双向、随机访问5中类型。
注意:所有的迭代器都支持++运算符,比如P++或++P
1、输入迭代器
Input lterator能单步向前迭代元素,不允许修改由该类迭代器引用的元素。输入迭代器用于从一个对象中不断读出元素。支持++与*操作符
格式:istream iterator<要从流中读取的数据类型>迭代器名(绑定的流);//创建的时候,就会调用标准输入
2、输出迭代器
Output lteratqr:该类迭代器和Input lterator极其相似,也只能单步向前迭代元素,不同的是该类迭代器对元素只有写的权力。向对象不断添加元素。ostream _iterator<要从流中读取的数据类型>迭代器名(绑定的流,元素分隔符);
3、正向迭代器
假设 p是一个正向迭代器,则p支持以下操作:++p,p++,*p。此外,两个正向迭代器可以互相赋值,还可以用==和!=运算符进行比较
4、双向迭代器
双向迭代器具有正向迭代器的全部功能。除此之外,若p是一个双向迭代器,则一p和p一都是有定义的。-p使得p朝和++p相反的方向移动。
5、随机访问迭代器
也是双向迭代器,但能够在序列中的任意两个位置之间进行跳转,如指针、使用vector的begin()、end()函数得到的迭代器
实现一个超市购物系统
#include <iostream>
#include <string>
#include<iomanip>#include<vector>
#include<list>
#include<map>
#include<algorithm>
#include<array>using namespace std;
/*
1)利用今天学习的容器知识,用C++实现一个 模拟超市的购物流程提示:先存钱到变量拿一个购物篮构建一个超市进入购物(循环)结算环节打印小票用面向过程和面向对象编程思想分别实现分析:定义一个钱包 wallet定义一个数据结构来描述超市 {商品名称,价格} map vector描述购物过程:while(1){} 购物篮:品名,单价,数量结算:遍历购物篮 打印小票并汇总价格
*/float wallet=0;
float total=0.0f;//抽象超市
map<string,float>market={{"香肠",3.5},{"鸡蛋",2},{"芙蓉王",25},{"洗衣机",200},{"方便面",5}
};//购物车
struct bar
{float price;int num;};map<string,struct bar> shoppingCar;int main()
{string goods_name;int goods_num;shoppingCar.clear();cout<<"请发钱";cin>>wallet;cout<<"==商品名称=========单价========"<<endl;for(auto e:market){cout<<e.first<<":"<<e.second<<endl;}while(1){cout<<"请输入你要购买的商品名称:";cin>>goods_name;cout<<endl;if(goods_name=="exit") break;cout<<"请输入你要购买的商品数量:";cin>>goods_num;if(market.find(goods_name)!=market.end()){if(shoppingCar.find(goods_name)==shoppingCar.end()){struct bar temp;temp.price=market[goods_name];temp.num=goods_num;shoppingCar[goods_name]=temp;}else{shoppingCar[goods_name].num=shoppingCar[goods_name].num+goods_num;}}else{cout<<"查无此商品"<<endl;}for(auto e:shoppingCar){cout<<"{"<<e.first<<":["<<e.second.num<<","<<e.second.price<<"]} ";}cout<<endl;}cout<<"========老郭家超市=========="<<endl;cout<<"商品名称\t商品单价\t商品数量\t"<<endl;for(auto e:shoppingCar){cout<<e.first<<"\t"<<e.second.price<<"\t"<<e.second.num<<endl;total=total+e.second.num*e.second.price;}cout<<"============================="<<endl;cout<<"本次应付:"<<total<<endl;return 0;
}
#include <iostream>
#include <string>
#include<iomanip>#include<vector>
#include<list>
#include<map>
#include<algorithm>
#include<array>using namespace std;
/*分析:顾客:customer属性:姓名钱包行为:购物付款查看钱包余额超市:market属性:名字货品行为:添加商品账目查看结账*///购物车
struct bar
{float price;int num;};class market
{public:market(string name){this->market_name=name;box.clear();total=0.0f;}bool add_goods(string gname,float price){if(box.find(gname)!=box.end()){return false;}else{box[gname]=price;return true; }}float checkout(const map<string,bar>&shoppingCar){float sum=0;for(auto e:shoppingCar){cout<<e.first<<"\t"<<e.second.price<<"\t"<<e.second.num<<endl;sum=sum+e.second.num*e.second.price;}total=total+sum;cout<<"本次应付款:"<<sum<<"元"<<endl;return sum; }float getAccount() const{return total;}map<string,float>& getBox(){return box;}private:string market_name;map<string,float> box;float total;};class customer
{public:customer(string name,float money){this->cname=name;this->wallet=money;}map<string,bar>& shopping(map<string,float>&box){static map<string,bar> shoppingCar;shoppingCar.clear();string goods_name;int goods_num;while(1){cout<<"请输入你要购买的商品名称:";cin>>goods_name;cout<<endl;if(goods_name=="exit") break;cout<<"请输入你要购买的商品数量:";cin>>goods_num;if(box.find(goods_name)!=box.end()){if(shoppingCar.find(goods_name)==shoppingCar.end()){struct bar temp;temp.price=box[goods_name];temp.num=goods_num;shoppingCar[goods_name]=temp;}else{shoppingCar[goods_name].num=shoppingCar[goods_name].num+goods_num;}}else{cout<<"查无此商品"<<endl;}} return shoppingCar; }bool pay(float money){float temp=this->wallet-money;if(temp>=0){ this->wallet=this->wallet-money;return true;}elsereturn false;}float getBalance()const {return wallet;}private:string cname;float wallet;};int main()
{market superMarket("华润万家");superMarket.add_goods("香肠",3);superMarket.add_goods("芙蓉王",30);superMarket.add_goods("玉米",5);superMarket.add_goods("披萨",30);superMarket.add_goods("鸡蛋",2);customer laoma("老马",300);map<string,bar>sCar= laoma.shopping(superMarket.getBox());float money=superMarket.checkout(sCar);laoma.pay(money);cout<<superMarket.getAccount();return 0;
}
二、智能指针
1、简介
本质上就是一个类、智能指针其实是⼀个类,实质就是重载了->和*操作符的类,由类来实现对内存的 管理,确保即使有异常产⽣,也可以通过智能指针类的析构函数完成内存的释放。 智能指针的⾏为类似常规指针,重要的区别在于智能指针负责⾃动释放所指向的对 象。
STL提供给我们提供了四种智能指针类型,除了下边列出的三种,还有C++98标准
auto_ptr智能指针,C+11已将将其摒弃。C++11 标准新引⼊了 这 3 个智能指针:
shared_ptr : 允许多个智能指针指向同⼀个对象
unique_ptr : ⼀个指针“独占”所指向的对象
weak_ptr : 弱引⽤,指向shared_ptr所管理的对象
2、unique_ptr
unique_ptr它提供了对动态分配内存的独占所有权的管理。unique_ptr确保同⼀时 间只有⼀个unique_ptr实例可以拥有⼀个对象的指针,从⽽避免了资源的多重释放 问题。当 std::unique_ptr 被销毁时,它所指向的对象也会被⾃动销毁。
unique_ptr 智能指针是以模板类的形式提供的,unique_ptr(T 为指针所指数 据的类型),定义在头⽂件,并位于 std 命名空间中。
特点:
轻量级:没有额外的引⽤计数开销,因此效率较⾼。
不可复制: std::unique_ptr 不能被复制,但可以通过 std::move 转移 所有权。
⾃动释放: 当 unique_ptr 离开作⽤域时,它所管理的对象会被⾃动删除
#include <iostream>
#include <string>
#include<memory>
using namespace std;class stu
{
public:string name;int age;stu(){name="sdf";age=0;}~stu(){cout<<"stu析构函数"<<endl;}};int main()
{//unique_ptr<int> ptr(new int(0));//唯一智能指针通过 * 运算符来访问托管对象
// *ptr=*ptr+10;
// cout<<*ptr<<endl;
//
// unique_ptr<stu> ptr1(new stu);
// cout<<ptr1->name<<endl;
// cout<<(*ptr1).name<<endl;//智能指针绑定动态数组 //unique_ptr<int[]> ptr(new int[3]{11,22,33});//唯一智能指针可以通过move函数来转移接管对象的所有权,转移成功后,该指针被设置为NULLPTR
// unique_ptr<stu> ptr1(new stu);
// unique_ptr<stu> ptr2=std::move(ptr1);
// cout<<ptr2->name<<endl;
// if(ptr1==nullptr)
// cout<<"ptr1为空指针"<<endl;
// else
// cout<<"ptr1不是空指针"<<endl;stu *pt=new stu;unique_ptr<stu> ptr1(pt);// ptr1.release();//让智能指针解除对托管对象之间的绑定关系,但是不会删除绑定对象
// if(ptr1==nullptr)
// cout<<"ptr1为空指针"<<endl;
// else
// cout<<"ptr1不是空指针"<<endl;//cout<<ptr1->name;//ptr1.reset();//解除绑定的同时 将智能指针设置为NULLPTR 会删除绑定对象cout<<"=======================";//通过get方法可以获取接管对象的地址cout<<pt<<":"<<ptr1.get()<<endl;return 0;
}