1.remove
remove(first, last, val); //删除first到last之间所有值为val的元素
remove只是通过迭代器的指针向后移动来删除,将没有被删除的元素放在链表的前面,并返回一个指向新的位置的迭代器。由于remove()函数不是vector成员函数,因此不能调整vector容器的长度。(对vector来说)remove()函数并不是真正的删除,要想真正删除元素则可以使用erase()或者resize()函数。
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
void printV(vector<int>& v){
int size = v.size();
printf(":--------------------------------------\n");
printf("size=%d\n", size);
auto it = v.begin();
for(; it != v.end();it++){
cout << *it << " ";
}
printf("\n--------------------------------------;\n");
}
int main(){
vector<int>v1;
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);
v1.push_back(7);
v1.push_back(11);
v1.push_back(16);
printV(v1);
v1.erase(remove(v1.begin(),v1.end(),3));
printV(v1);
//如果想删除必须加erase
return 0;
}
:--------------------------------------
size=6
1 3 5 7 11 16
--------------------------------------;
:--------------------------------------
size=5
1 5 7 11 16
--------------------------------------;
2.remove_if
函数原型:ForwardIterator remove_if (ForwardIterator first, ForwardIterator last,
UnaryPredicate pred);
简单的说就是:remove_if(first, last, pred) 从first到last中将满足条件pred的元素删除
这个函数就是按条件删除元素
remove_if的参数是迭代器,通过迭代器无法得到容器本身,而要删除容器内的元素只能通过容器的成员函数erase来进行,因此remove系列函数无法真正删除元素,只能把要删除的元素移到容器末尾并返回要被删除元素的迭代器,然后通过erase成员函数来真正删除。
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
void printV(vector<int>& v){
int size = v.size();
printf(":--------------------------------------\n");
printf("size=%d\n", size);
auto it = v.begin();
for(; it != v.end();it++){
cout << *it << " ";
}
printf("\n--------------------------------------;\n");
}
bool IfEqualThree(int ret) {
return ret == 3;
}
int main() {
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(3);
printV(v);
v.erase(remove_if(v.begin(), v.end(), IfEqualThree), v.end());
printV(v);
}
:--------------------------------------
size=7
1 2 3 3 4 5 3
--------------------------------------;
:--------------------------------------
size=4
1 2 4 5
--------------------------------------;
3.设计模式
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
设计模式被分为三大类:创建型,结构型和行为型模式。
(1)单例模式
单例模式保证一个类只生成一个实例对象。也就是说在整个程序运行过程中,该类只有一个对象。
单例的设计步骤:
1.构造函数私有化
2.在类中定义一个静态指针,指向本类的的静态私有对象成员
3.提供一个全局的静态方法,用于获取上面生成的对象
(静态访问点)
单例分为懒汉式和饿汉式,区别在于对象创建时间不同。懒汉式是在第一次使用对象时创建,而饿汉式则在程序启动时就将对象创建好,无论是否使用。
(1)饿汉式
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
class UserDAO{
//1.私有化构造方法
UserDAO(){}
//2.生成一个静态的本类成员,并且私有的
static UserDAO* dap;//静态的需要在类外赋值
static int count;
public:
//3.提供一个共有的静态方法,用于获取上面的静态成员对象
static UserDAO* getinstance(){
count ++;
return dap;
}
void release(){
count--;
if(count==0){
delete dap;
dap=NULL;//必须让dap指向NULL否则会指向别的地方
}
}
};
UserDAO* UserDAO::dap=new UserDAO;
int UserDAO::count=0;
int main(){
UserDAO* dap1=UserDAO::getinstance();
UserDAO* dap2=UserDAO::getinstance();
UserDAO* dap3=UserDAO::getinstance();
printf("dap1=%x\n",dap1);
printf("dap2=%x\n",dap2);
printf("dap3=%x\n",dap3);
dap1->release();
dap2->release();
dap3->release();
return 0;
}
dap1=1870c20
dap2=1870c20
dap3=1870c20
(2)懒汉式
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
class usermanage{
private:
usermanage(){}
public:
static usermanage* getinstanc(){
if(m_instance==NULL){
m_instance=new usermanage;
}
count++;
return m_instance;
}
static void release(){
count--;
if(m_instance!=NULL&&count==0){
delete m_instance;
m_instance=NULL;
}
}
private:
static usermanage* m_instance;
static int count;
};
usermanage* usermanage::m_instance=NULL;
int usermanage::count=0;
int main(){
usermanage* num1=usermanage::getinstanc();
usermanage* num2=usermanage::getinstanc();
if(num1=num2){
cout<<"同一个对象"<<endl;
}else{
cout<<"不是同一个对象"<<endl;
}
num1->release();
num2->release();
return 0;
}
同一个对象
饿汉式在初始化对象的时候就创建了一个对象,而懒汉式则每次使用对象前都要判断该对象是否存在,不存在创建对象。
(3)关于多线程的问题
由于懒汉式在每次获取对象指针时都要进行判断,多线程下可能会导致对象被多次创建
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include<unistd.h>
using namespace std;
//懒汉式单例
class usermanage{
private:
usermanage(){
printf("构造函数被调用\n");
sleep(5);
}
static int count;
static usermanage* m_instance;
public:
static usermanage* getinstance(){
if(m_instance==NULL){
m_instance=new usermanage;
}
count++;
return m_instance;
}
static void release(){
count--;
if(m_instance!=NULL&&count==0){
delete m_instance;
m_instance=NULL;
}
}
};
usermanage* usermanage::m_instance=NULL;
int usermanage::count=0;
void* func(void* arg){
usermanage* mu=usermanage::getinstance();
}
int main(){
pthread_t id;
for(int i=0;i<10;i++){
pthread_create(&id,NULL,func,NULL);
pthread_detach(id);//由系统来回收线程所占用资源。
}
pthread_exit(NULL);//主线程退出不影响其他进程运行
return 0;
}
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
上面创建了10个线程后,10个线程同时去获取对象指针,这是对象还没有创建而构造函数又是一个很费时的操作,导致10个线程都去调用构造函数进行对象创建。
为了在多线程情况下正常运行,我们需要使用一些线程同步机制来控制对象的创建。
互斥锁
class usermanage{
private:
usermanage(){
printf("构造函数被调用\n");
sleep(5);
}
static int count;
static usermanage* m_instance;
static pthread_mutex_t mutex;
public:
static usermanage* getinstance(){
pthread_mutex_lock(&mutex);//上锁
if(m_instance==NULL){
m_instance=new usermanage;
}
pthread_mutex_unlock(&mutex);//解锁
count++;
return m_instance;
}
static void release(){
pthread_mutex_lock(&mutex);//上锁
count--;
if(m_instance!=NULL&&count==0){
delete m_instance;
m_instance=NULL;
}
pthread_mutex_unlock(&mutex);//解锁
}
};
usermanage* usermanage::m_instance=NULL;
int usermanage::count=0;
pthread_mutex_t usermanage::mutex=PTHREAD_MUTEX_INITIALIZER;
这样修改之后,可以保证单例模式能够在多线程下正常使用。但是这里有一个不好的地方就是,在每次获取对象时都要进行上锁和解锁的操作,这会带来很大的开销。实际上,当对象创建出来后进行调用时已经不需要上锁和解锁的操作,我们可以进一步优化代码
static usermanage* getinstance(){
if(m_instance==NULL){//增加一次判断,避免频繁的上锁和解锁
pthread_mutex_lock(&mutex);//上锁
if(m_instance==NULL){
m_instance=new usermanage;
}
pthread_mutex_unlock(&mutex);//解锁
}
count++;
return m_instance;
}
(2)工厂模式
(1)简单工厂模式
简单工厂也叫静态工厂,是一种由工厂对象决定创建出哪一种产品类的实例。
简单工厂模式中的各个角色如下:
1)工厂(Creator):负责创建所有实例的内部逻辑
2)抽象(Product):它是简单工厂所创建的所有对象的父类
3)具体产品(Concreate Product):它是简单工厂创建出来的具体产品
#include <iostream>
#include<string>
using namespace std;
class Operator{
public:
virtual int getresult(int a,int b)=0;
};
class add:public Operator{
int getresult(int a,int b){
return a+b;
}
};
class sub:public Operator{
int getresult(int a,int b){
return a-b;
}
};
class factory{
public:
Operator* createOperator(string name){
Operator* opt=NULL;
if(name=="加法"){
opt=new add;
}else if(name=="减法"){
opt=new sub;
}
return opt;
}
};
int main(){
factory *fl=new factory;
Operator *opt=fl->createOperator("加法");
cout<<opt->getresult(10,4)<<endl;
delete opt;
opt=fl->createOperator("减法");
cout<<opt->getresult(10,4)<<endl;
delete opt;
delete fl;
return 0;
}
14
6
(2)工厂方法模式
在工厂方法中,核心的工厂不再负责所有产品的创建,而是将具体的创建工作交给子类去完成,工厂类成为一个抽象工厂角色,仅给出具体工厂必须实现的接口。
(1)抽象工厂(creator)角色:他是工厂方法模式的核心,任何工厂类都必须实现这个接口。
(2)具体工厂(concrete creator)角色:是抽象工厂的一个实现,负责实例化产品对象。
(3)抽象(product)角色:它是工厂方法模式所创建的所有对象的父类,负责描述所有实例所共有的接口。
(4)具体产品(concrete product)角色:它是工厂方法模式所创建的具体实例对象。
#include <iostream>
#include<string>
using namespace std;
class Operator{
public:
virtual int getresult(int a,int b)=0;
};
class add:public Operator{
int getresult(int a,int b){
return a+b;
}
};
class sub:public Operator{
int getresult(int a,int b){
return a-b;
}
};
class obsfactory{
public:
virtual Operator* createOperator()=0;
};
class addfactory:public obsfactory{
Operator* createOperator()
{
Operator* opt=new add;
return opt;
}
};
class subfactory:public obsfactory{
Operator* createOperator()
{
Operator* opt=new sub;
return opt;
}
};
int main(){
obsfactory * oft=new addfactory;
Operator* opt=oft->createOperator();
cout<<"加法结果"<<opt->getresult(10,4)<<endl;
delete oft;
delete opt;
oft=new subfactory;
opt=oft->createOperator();
cout<<"减法结果"<<opt->getresult(10,4)<<endl;
delete oft;
delete opt;
return 0;
}
加法结果14
减法结果6
(3)抽象工厂模式
工厂类负责创建抽象产品的子类的实例。
抽象工厂模式的角色如下:
抽象工厂(Creator):它是抽象工厂模式的核心,包含对多个产品线的声明,任何工厂类都必须实现这个接口。
(1)具体工厂(Concrete Creator):具体工厂是抽象工厂的一个实现,负
(2)责实例化某个产品线中的产品对象
(3)抽象产品(Product):它是抽象工厂模式所创建的所有对象的父类,负责描述所有实例共有的接口
(4)具体产品(Concrete Product):它是抽象工厂模式所创建的具体对象。
#include <iostream>
#include<string>
using namespace std;
class clothes{
public:
virtual void show()=0;
};
class s_jacket:public clothes{
public:
void show(){
cout<<"森马的夹克"<<endl;
}
};
class s_jeans:public clothes{
public:
void show(){
cout<<"森马的牛仔裤"<<endl;
}
};
class h_jacker:public clothes{
public:
void show(){
cout<<"海澜之家的夹克"<<endl;
}
};
class h_jeans:public clothes{
public:
void show(){
cout<<"海澜之家的牛仔裤"<<endl;
}
};
class absfactory{
public:
virtual clothes*createjacket()=0;
virtual clothes*createjeans()=0;
};
//森马工厂
class s_factory:public absfactory{
public:
clothes* createjacket(){
clothes *p=new s_jacket;
return p;
}
clothes* createjeans(){
clothes *p=new s_jeans;
return p;
}
};
//海澜之家工厂
class h_factory:public absfactory{
public:
clothes* createjacket(){
clothes *p=new h_jacker;
return p;
}
clothes* createjeans(){
clothes *p=new h_jeans;
return p;
}
};
void func(absfactory*abs){
clothes* pjacket=abs->createjacket();
clothes* pjeans=abs->createjeans();
pjacket->show();
pjeans->show();
delete pjacket;
delete pjeans;
}
int main(){
absfactory* abs=new s_factory;
func(abs);
delete abs;
abs=new h_factory;
func(abs);
delete abs;
return 0;
}
森马的夹克
森马的牛仔裤
海澜之家的夹克
海澜之家的牛仔裤
(3)装饰模式
装饰(Decorator) 模式又称为包装模式,可以通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一一个替换方案。
装饰模式把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要使用对象时,客户端就可以有选择地、按顺序地使用装饰功能包装对象,动态地给一个对象添加些额外的功能。就增如功能来说,装饰模式比生成子类的方式更为灵活,在不改变接口的条件下。
(1)需要扩展一个类的功能,或给一个类增加附加功能时。
(2)需要动态地给一个对象增加功能,这些功能也可以动态地撤销。
(3)需要增加一些基本功能 的排列组合以产生更多的功能,使用继承变得不现实。
装饰者模式的角色组成如下:
(1)抽象构件角色(Component):给出一个抽象接口,以规范准备增加附加功能的对象。
(2)具体构件角色( Concrete Component):定义一个将要增加附加功能的类。
(3)装饰角色(Decorator):拥有一个构件(Component) 对象的实例,并定义一一个与抽象构件接口一致的接口。
(4)具体装饰角色(Concrete Decorator):负责给构件对象增加附加的功能。
#include <iostream>
#include<string>
using namespace std;
//饼的基类
class Cake{
public:
virtual string getname()=0;
virtual double getprice()=0;
protected:
string name;
};
//手抓饼
class shreddedcake:public Cake{
public:
shreddedcake(){
name="手抓饼";
}
string getname(){
return name;
}
double getprice(){
return 5;
}
};
//配料的基类
class condiment:public Cake{
protected:
Cake* cake;
};
//加鸡蛋的饼
class egg:public condiment{
public:
egg(Cake* cake){
this->cake=cake;
}
string getname(){
return cake->getname()+"+鸡蛋";
}
double getprice(){
return cake->getprice()+1.5;
}
};
//加里脊的饼
class tenderloin:public condiment{
public:
tenderloin(Cake* cake){
this->cake=cake;
}
string getname(){
return cake->getname()+"+里脊";
}
double getprice(){
return cake->getprice()+2;
}
};v
int main(){
shreddedcake* pc=new shreddedcake;
cout<<pc->getname()<<" "<<pc->getprice()<<"元"<<endl;
tenderloin* pst=new tenderloin(pc);
cout<<pst->getname()<<" "<<pst->getprice()<<"元"<<endl;
egg* pse=new egg(pst);
cout<<pse->getname()<<" "<<pse->getprice()<<"元"<<endl;
delete pse;
delete pst;
delete pc;
return 0;
}
手抓饼 5元
手抓饼+里脊 7元
手抓饼+里脊+鸡蛋 8.5元