C++11:智能指针
C++11新增了 auto_ptr unique_ptr shared_ptr weak_ptr 四种指针,第一个auto_ptr已经被弃用
unique_ptr 独占所指向的对象
智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象,当栈对象的生命周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏
一.auto_ptr
//p2指针取代了p1,访问p1指针会报错,auto_ptr 存在潜在的内存崩溃,已弃用
auto_ptr<string> p1;
auto_ptr<string> p2;
p2 = p1;
二.unique_ptr
unique_ptr实现独占式拥有和严格拥有概念,保证同一时间内只有一个智能指针指向该对象,避免资源泄漏
unique_ptr<string> p3;
unique_ptr<string> p4;
p4 = p3; //会报错
三.shared_ptr
shared_ptr实现共享式指针,多个智能指针可以指向相同对象,该对象会在最后一个引用被销毁后释放
通过成员函数use_count()来查看资源的所有者个数,调用release()释放资源所有权
shared_ptr 允许多个指针指向同一个对象,weak_ptr 类指向 shared_ptr 所管理的对象
shared_ptr是一种智能指针,作用如同指针,但会用引用计数记录不同的shared_ptr指向同一个对象,一旦对象的引用计数变为0,对象就会自动删除
都定义在 memory 头文件中
class Counter
{
public:
Counter() : s(0), w(0){};
int s; //shared_ptr的引用计数
int w; //weak_ptr的引用计数
};
template <class T>
class WeakPtr; //为了用weak_ptr的lock(),来生成shared_ptr用,需要拷贝构造用
template <class T>
class SharedPtr
{
public:
SharedPtr(T* p = 0) : _ptr(p)
{
cnt = new Counter();
if (p)
cnt->s = 1;
cout << "in construct" << cnt->s << endl;
}
~SharedPtr()
{
release();
}
SharedPtr(SharedPtr<T> const& s)
{
cout << "in copy con" << endl;
_ptr = s._ptr;
(s.cnt)->s++;
cout << "copy construct" << (s.cnt)->s << endl;
cnt = s.cnt;
}
SharedPtr(WeakPtr<T> const& w)
{
cout << "in w copy con" << end;
_ptr = w._ptr;
(w.cnt)->s++;
cout << "copy w construct" << (w.cnt)->s << endl;
cnt = w.cnt;
}
SharedPtr<T> &operator=(SharedPtr<T> &s)
{
if (this != &s)
{
release();
(s.cnt)->s++;
cout << "assign construct" << (s.cnt)->s << endl;
cnt = s.cnt;
_ptr = s._ptr;
}
return *this;
}
T &operator* ()
{
return *_ptr;
}
T *operator->()
{
return _ptr;
}
friend class WeakPtr<T>; //方便weak_ptr与shared_ptr设置引用计数和赋值
protected:
void release()
{
cnt->s--;
cout << "release " << cnt->s << endl;
if (cnt->s < 1)
{
delete _ptr;
if (cnt->w < 1)
{
delete cnt;
cnt = NULL;
}
}
}
private:
T* _ptr;
Counter* cnt;
};
int main()
{
string* s1 = new string("s1");
shared_ptr<string> ps1(s1);
shared_ptr<string> ps2;
ps2 = ps1;
cout << ps1.use_count() << endl; // 2
cout << ps2.use_count() << endl; // 2
cout << ps1.unique() << endl; // 0
string* s3 = new string("s3");
shared_ptr<string> ps3(s3);
cout << (ps1.get()) << endl; //033AEB48
cout << ps3.get() << endl; //033B2C50
swap(ps1, ps3); //交换所拥有的对象
cout << (ps1.get()) << endl; //033B2C50
cout << ps3.get() << endl; //033AEB48
cout << ps1.use_cout() << endl; // 1
cout << ps2.use_cout() << end; // 2
ps2 = ps1;
cout << ps1.use_cout() << endl; // 2
cout << ps2.use_cout() << endl; // 2
ps1.reset(); //放弃ps1的拥有权,引用计数减少
cout << ps1.use_cout() << endl; // 0
cout << ps2.use_cout() << endl; // 1
}
shared_ptr<T> p //空智能指针,可以指向类型为T的对象 unique_ptr<T> p p //将p用作一个条件判断,若p指向一个对象,则为true *p //解引用p获得它指向的对象 p->get() //返回p中保存的指针 swap(p, q) //交换p q中的指针 p.swap(q)
Shared_ptr<T> p(q)
Shared_ptr<T> p(q, d)
Shared_ptr<T> p(p2, d)
p.reset()
p.reset(q)
p.reset(q, d)
#include <memory>
#include <iostream>class Test
{
public:
Test()
{
std::cout << "Test()" << std::endl;
}
~Test()
{
std::cout << "~Test()" << std::endl;
}
};int main()
{
std::shared_ptr<Test> p1 = std::make_shared<Test>();
std::cout << "1 ref:" << p1.use_count() << std::endl;
{
std::shared_ptr<Test> p2 = p1;
std::cout << "2 ref:" << p1.use_count() << std::endl;
}
std::cout << "3 ref:" << p1.use_count() << std::endl;
return 0;
}
1.初始化
#include <iostream> using namespace std; int main() { //默认初始化的智能指针保存着一个空指针 shared_ptr<string> p1; if(!p1) cout<<"p1==NULL"<<endl; //初始化 shared_ptr<string> p2(new string); if(p2 && p2->empty()){ *p2 = "helloword" cout<< *p2 <<endl; } //一般的初始化方式 shared_ptr<string> print(new string("normal usage!")); cout<<*print<<endl; //推荐安全的初始化方式 shared_ptr<string> print1 = make_shared<string>("safe uage!") cout<< *pint1 <<endl; }
// 错误初始化方式 shared_ptr<int> pa = new int(1); int* p = new int(32); shared_ptr<int> pp(p); cout<< *pp << endl; delete p; cout<< *pp <<endl;
2.get()
get()返回一个内置指针,指向智能指针的管理对象
#include <iostream> #include <memory> using namespace std; void useShared_ptr(int* p) { cout<< *p <<endl; } void delePointer(int* p) { delete p; } int main(int argc, char* argv[]) { shared_ptr<int> p1 = make_shared<int> (32); // shared_ptr<int> p2(p1.get()) 错误,他们各自有内存的引用计数,不能拷贝过去 useShared_ptr(p1.get()); // delePointer(p1.get()) 错误 return 0; }
3.make_shared<>()
安全分配和使用动态内存的方法是调用 make_shared() 标准库函数,此函数在动态内存中分配一个对象并初始化它,返回此对象的shared_ptr
#include <iostream> using namespace std; int main() { shared_ptr<int> p3 = make_shared<int>(42); cout<< *p3 <<endl; shared_ptr<string> pstr = make_shared<string>("99999"); cout<< *pstr <<endl; shared_ptr<int> pint = make_shared<int>(); cout<< *pint <<endl; auto pau = make_shared<string>("auto"); cout<< *pau <<endl; }
4.shared_ptr的拷贝和赋值
5.引用计数
四.weak_ptr
shared_ptr智能指针有可能导致内存泄漏的风险,当两个对象相互使用一个shared_ptr成员变量指向对方,会造成循环引用,使引用计数失效,从而导致内存泄漏
weak_ptr是用来解决shared_ptr相互引用造成死锁问题,是一种不控制对象生命周期的智能指针
weak_ptr设计的目的是为了配合shared_ptr而引入的一种智能指针来协助工作,它是对象的一种弱引用
weak_ptr一般通过shared_ptr来构造,通过expired函数检查原始指针是否为空,lock来转化为shared_ptr
template <class T>
class WeakPtr
{
public: //给出默认构造和拷贝构造,其中拷贝构造不能有从原始指针进行构造
WeakPtr()
{
_ptr = 0;
cnt = 0;
}
WeakPtr(SharedPtr<T>& s) : _ptr(s._ptr), cnt(s.cnt)
{
cout << "w con s" << endl;
cnt->w++;
}
WeakPtr(WeakPtr<T>& w) : _ptr(w._ptr), cnt(w.cnt)
{
cnt->w++;
}
~WeakPtr()
{
release();
}
WeakPtr<T> &operator=(WeakPtr<T> &w)
{
if (this != &w)
{
release();
cnt = w.cnt;
cnt->w++;
_ptr = w._ptr;
}
return *this;
}
WeakPtr<T> &operator=(SharedPtr<T> &s)
{
cout << "w = s" << endl;
release();
cnt = s.cnt;
cnt->w++;
_ptr = s._ptr;
return *this;
}
SharedPtr<T> lock()
{
return SharedPtr<T>(*this);
}
bool expired()
{
if (cnt)
{
if (cnt->s > 0)
{
cout << "empty" << cnt->s << endl;
return false;
}
}
return true;
}
friend class SharedPtr<T>; //方便weak_ptr与shared_ptr设置引用计数和赋值
protected:
void release()
{
if (cnt)
{
cnt->w--;
cout << "weakptr release" << cnt->w << endl;
if (cnt->w < 1 && cnt->s < 1)
{
//delete cnt;
cnt = NULL;
}
}
}
private:
T* _ptr;
Counter* cnt;
};