shared_ptr.是c++为了提高指针安全性而添加的智能指针,方便了内存管理。功能强大,但是也要注意以下问题:
1、不能用普通指针给它赋值
int* pIntValue = new int;
shared_ptr<int> shPtr= pIntValue; // 语法错误
shPtr = pIntValue; // 语法错误
2、shared_ptr多次引用同一数据,会导致两次释放同一内存。
int* pIntArr = new int[10];
shared_ptr<int> sp1(pIntArr );
shared_ptr<int> sp2(pIntArr );// 析构时两次释放同一内存
3、使用shared_ptr包装this指针带来。
错误作法:
class Test
{
public:
Test() {};
~Test() {};
public:
shared_ptr<Test> sget()
{
return shared_ptr<Test>(this);
}
};
Test one;
shared_ptr<Test> two= one.sget();// 两次释放t对象破坏堆栈
// 两次释放one对象破坏堆栈!!!!!
// 两次释放one对象破坏堆栈!!!!!
// 两次释放one对象破坏堆栈!!!!!
正确作法:
class Test: public enable_shared_from_this<Test>
{
public:
Test() {};
~Test() {};
public:
shared_ptr<Test> sget()
{
return shared_from_this();
}
};
Test one;
shared_ptr<Test> two= one.sget();// 正确了。
4、shared_ptr循环引用导致内存泄露。
class father;
class son;
typedef shared_ptr<father> father_ptr;
typedef shared_ptr<son> son_ptr;
class father
{
public:
~father() {}
son_ptr m_son;
};
class son
{
public:
~son() {}
father_ptr m_father;
};
father_ptr f(new father());
son_ptr s(new son);
f->m_father= s;
s->m_son= f;
f的引用计数为2,s的计数也为2,退出时,shared_ptr所作操作就是简单的将计数减1,如果为0则释放,显然,这个情况下,引用计数不为0,于是造成f和s所指向的内存得不到释放,导致内存泄露。
5、在多线程程序中使用shared_ptr的问题。
class Test
{
public:
Test() {}
~Test() {}
// 更多的函数定义…
};
void thread_fun(shared_ptr<Test> sp)
{
// !!!在这大量使用sp指针.
shared_ptr<Test> tmp = sp;
}
shared_ptr<Test> sp1(new Test);
thread t1(bind(&fun, sp1));
thread t2(bind(&fun, sp1));
t1.join();
t2.join();
由于多线程同时访问智能指针,并将其赋值到其它同类智能指针时,可能发生两个线程同时在操作引用计数,而导致计数失败或无效等情况。
使用weak_ptr可以解决类多线程中的问题。
void fun(weak_ptr<Test> wp)
{
shared_ptr<Test> sp = wp.lock;
if (sp)
{
// 在这里可以安全的使用sp指针.
}
else
{
// 指针无效
}
}