C++没有类似Java、C#等语言的垃圾回收机制,内存管理是最为头痛的工作。
new、delete以及指针的不恰当运用是C++中造成资源获取/释放问题的根源。
智能指针是解决这些问题的一种方案,boost.smart_ptr库提供了六种智能指针,包括:
scoped_ptr
、 scoped_array
、 shared_ptr
、 shared_array
、 weak_ptr
、 intrusive_ptr
它们都是轻量级对象,速度与原始指针相差无几,都是异常安全的。
要使用smart_ptr组件,需要包含头文件 #include <boost/smart_ptr.hpp>
shared_ptr
是一个最像指针的“智能指针”,是boost.smart_ptr库中最有价值、最重要的组成部分。已收入了C++11标准。
shared_ptr
是引用计数的智能指针,可以被自由的拷贝和赋值,在任意地方共享它,当没有代码使用(引用计数为0)时删除被包装的动态分配的对象。
shared_ptr
可以安全的放到标准容器中,是在STL容器中存储指针的最标准解法。
应用举例:
#include "stdafx.h"
#include <iostream>
#include <cassert>
#include <string>
#include <vector>
#include <boost/smart_ptr.hpp>
using std::cout;
using std::endl;
using std::string;
using std::vector;
int _tmain(int argc, _TCHAR* argv[])
{
boost::scoped_ptr<string> pstr(new string("scoped_ptr test"));
assert(pstr);
assert(pstr != nullptr);
*pstr = "hello test";
cout << *pstr << ": " << pstr->size();
boost::scoped_ptr<string> another_p_str;
assert(!another_p_str);
if (NULL == another_p_str)
{
cout << "
Null pointer!
";
}
boost::shared_ptr<string> sps(boost::make_shared<string>("shared_ptr_test"));
cout << "
" << sps->c_str() << endl;
boost::shared_ptr<string> sps2(sps);
*sps2 = "shared_ptr is smart!";
cout << *sps << endl;
assert(sps == sps2);
//shared_ptr用于容器
typedef vector<boost::shared_ptr<int>> VSI;
VSI v;
v.push_back(boost::make_shared<int>(1));
v.push_back(boost::make_shared<int>(2));
v.push_back(boost::make_shared<int>(3));
v.push_back(boost::make_shared<int>(4));
v.push_back(boost::make_shared<int>(5));
cout << "
Vevtor: ";
boost::shared_ptr<int> pv = v[0];
*pv = 1000;
for (size_t i = 0; i < v.size(); ++i)
{
cout << *v[i] << " ";
}
return 0;
}
在开发实践中,个人觉的最应当使用智能指针的两种场合:
(1) 应用于标准容器
在使用容器管理大量对象指针的时候,必须编写额外的大量代码来保证指针最终被正确释放,通常很麻烦而且容易出错。将shared_ptr
作为容器的元素,如vector<shared_ptr<T> >
,与存储原始指针的容器所能实现的功能几乎一样,而不用担心资源泄漏。
(2) 应用于工厂模式
在程序中编写自己的工厂类或者工厂函数时,通常需要在堆上使用new动态分配一个对象然后返回对象的指针。这种做法很不安全,应为很容易忘记对指针调用delete。
使用shared_ptr
可以解决这个问题,只需要修改工厂方法的接口,不再返回一个原始指针,而是返回一个被shared_ptr
包装的智能指针,这样可以很好地保护系统资源,而且会更好地控制对接口的使用。
使用代码来解释shared_ptr
应用于工厂模式的用法:
#ifndef OPERATION_H_
#define OPERATION_H_
#include <boost/smart_ptr.hpp>
enum OperationType
{
ADD,
SUB,
MUL,
DIV
};
//运算基类
class Operation
{
public:
virtual double GetResult() const = 0;
Operation()
: m_Operand1(0.0)
, m_Operand2(0.0)
{
}
void SetOperrand1(const double operand1)
{
m_Operand1 = operand1;
}
double GetOperand1() const
{
return m_Operand1;
}
void SetOperrand2(const double operand2)
{
m_Operand2 = operand2;
}
double GetOperand2() const
{
return m_Operand2;
}
protected:
virtual ~Operation(){}
protected:
double m_Operand1;
double m_Operand2;
};
//加法
class Add : public Operation
{
public:
double GetResult() const override;
};
//减法
class Sub : public Operation
{
public:
double GetResult() const override;
};
//乘法
class Mul : public Operation
{
public:
double GetResult() const override;
};
//除法
class Div : public Operation
{
public:
double GetResult() const override;
};
//工厂类
class OperationFactory
{
public:
static boost::shared_ptr<Operation> CreateOperation(OperationType type)
{
boost::shared_ptr<Operation> oper;
switch (type)
{
case ADD:
oper = boost::make_shared<Add>();
break;
case SUB:
oper = boost::make_shared<Sub>();
break;
case MUL:
oper = boost::make_shared<Mul>();
break;
case DIV:
oper = boost::make_shared<Div>();
break;
default: ;
}
return oper;
}
};
#endif
调用代码:
//通过工厂方法创建对象
auto pOper = OperationFactory::CreateOperation(MUL);
if (nullptr != p)
{
pOper->SetOperrand1(100); //可以像普通指针一样使用
pOper->SetOperrand2(123);//不必担心内存泄漏,shared_ptr会自动管理指针
cout << "
" << pOper->GetResult();
}
C++11标准中std::shared_ptr
,功能与boost::shared_ptr
基本相同,完全可以定价互换。
包含头文件#incude <memory>