关于智能指针和内存管理的说明可以先阅读这篇文章:[C++内存管理] 。本次主要讨论的是设计模式,将智能指针和设计模式结合使用,运用恰当的话可以帮助我们减少编译时间、适应变化甚至在不使用虚函数的情况下实现多态。
1 桥接模式
桥接模式是一种结构型设计模式,主要是将抽象层和实现层进行解耦,在实现桥接模式时,scoped_ptr和shared_ptr都可以实现,但是因为shared_ptr支持拷贝和赋值,使用shared_ptr实现桥接模式变得更加灵活因此,shared_ptr更适合用来实现桥接模式。
桥接模式可以任意改变实现方式并隐藏外部对其的感知。减少了源文件之间的编译依赖。使用shared_ptr实现桥接模式也解决了指针的共享和引用计数问题。 具体实现如下:
#include <iostream>
#include <memory>
using namespace std;
class Print{
private:
class impl;
shared_ptr<impl> p;
public:
Print();
void print_f();
};
class Print::impl{
public:
void print_f(){
cout<<"this is impl output"<<endl;
}
};
Print::Print():p(new impl()){};
void Print::print_f(){p->print_f();};
int main()
{
Print f;
f.print_f();
return 0;
}
以上代码运行结果如下:
this is impl output
2 工厂模式
工厂模式是一种创建型模式,提供了根据不同需要创建不同类型对象的方式,在实际编码中,实现工厂类时需要使用new创建对象,通过获取创建对象的指针进行任务处理。这种方式在C++支持智能指针之前使用的最普遍的方式,仔细思考这种方式实际上是有风险的。使用后如果忘记对指针指向的资源释放将会造成内存泄露的风险。
在工厂模式实现中使用shared_ptr就可以解决上述问题,在创建对象后返回一个被shared_ptr包裹着的原始指针,就可以很好的保护系统资源,避免内存泄露风险。下面的就实现了通过创建函数返回基类的智能指针。
//基类
class Shoes{
public:
virtual void f()=0;
virtual void g()=0;
};
//子类
class SportShoes: public Shoes{
public:
virtual void f(){
cout<<"f()"<<endl;
}
virtual void g(){
cout<<"g()"<<endl;
}
};
//工厂类
class Factory{
public:
shared_ptr<Shoes> create(){
return shared_ptr<Shoes>(new SportShoes);
}
};
int main()
{
Factory fa;
shared_ptr<Shoes>pShoes = fa.create();
pShoes->f();
pShoes->g();
return 0;
}
如上,代码运行结果为:
f()
g()
在shared_ptr的构造函数中,还可以支持在构造函数中指定指针析构时调用的函数,运用此种方法,可以帮助我们实现定制删除 器。使用方式如下:
void release_int(int *pInt){
cout<<"指针析构后就会调用我"<<endl;
}
int main()
{
int *pIntIn = new int(5);
shared_ptr<int> pInt(pIntIn,release_int);
return 0;
}
如上,程序代码运行结果如下:
指针析构后就会调用我
在上面的代码中,原生指针被智能指针包裹,并且为智能指针析构时指定了删除函数release_int;充分使用智能指针的这一特性,将会给实际编程提供很大的帮助。
3 总结
shared_ptr是C++中最重要且最有用的智能指针,通过它实现桥接、工厂等设计模式,更加显示了它的强大。另外,通过shared_ptr提供的工厂函数也进一步消除了new的操作。降低了指针在使用过程中产生的风险。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8