- 不带引用的智能指针
- 解决浅拷贝问题
- 防止浅拷贝方法1 重新定义拷贝构造函数
- 不带引用的智能指针
- 使用auto_ptr(不推荐)
- unique_ptr
- 带引用的智能指针
- shared_ptr
- 线程安全 ++ -- atomic_int
- 强智能指针循环引用(交叉引用)是什么问题?什么结果?怎么解决?
- 定义对象的时候,用强智能指针,引用对象的地方,使用弱智能指针
- weak_ptr
- 多线程访问共享对象的线程安全问题
- 解决
解决浅拷贝问题
templateclass CSmartPtr{ public: CSmartPtr(T *ptr = nullptr) : mptr(ptr){ } ~CSmartPtr(){ delete mptr; } T &operator* (){ return *mptr; } T *operator->(){ return mptr; } private: T *mptr; }; int main(){ CSmartPtr ptr1(new int); CSmartPtr ptr2(ptr1); }
这种情况会出现浅拷贝,delete俩次。
防止浅拷贝方法1 重新定义拷贝构造函数给当前对象重新开辟一块空间,用你的值来初始化我
CSmartPtr(const CSmartPtr&src){ mptr = new T(*src.mptr); } ~CSmartPtr(){ delete mptr; mptr = nullptr; }
但是这样会出现俩快资源,而用户就像管理一个资源
不带引用的智能指针 使用auto_ptr(不推荐)auto_ptrptr1(new int); auto_ptr ptr2(ptr1); *ptr2 = 20; cout << *ptr1;
这样会报错,因为auto_ptr只会管理最后一个资源,前面的指针全部置成null;所以说在容器里面vector< auto_ptr< int >> vec1; vec2(vec1),容器的拷贝构造和容器的赋值会引起vec1里面的指针全部置成nullptr
unique_ptr&> = delete; unique_ptr & operator=(const unique_ptr &) = delete;
unique_ptr和scoped_ptr一样都会把拷贝构造和赋值都和谐了,如果直接拷贝赋值就会报错。
c++11 右值引用 std::move得到当前变量的右值类型(右值引用的类型强转)
unique_ptrp1(new int); unique_ptr p2(std::move(p1));
之所以unique_ptr可以成功是因为它带右值引用的拷贝构造函数和赋值运算符的重载函数
unique_ptr(unique_ptr带引用的智能指针&&src) unique_ptr & operator=(unique_ptr &&src)
带引用技术的智能指针shared_ptr和weak_ptr
带引用计数:多个智能指针可以管理同一个资源
带引用计数:给每一个对象资源,匹配一个引用计数
智能指针 =》 资源的时候 =》 引用计数 + 1
智能指针 =》 不使用资源的时候 =》 引用计数 - 1 =》 != 0 0资源释放了
// 自己实现share_ptr(线程不安全)
#include "iostream" using namespace std; #include "memory" // 21点47分 template线程安全 ++ – atomic_int 强智能指针循环引用(交叉引用)是什么问题?什么结果?怎么解决?class RefCnt{ public: RefCnt(T *ptr = nullptr) : mptr(ptr){ if(mptr != nullptr){ mcount = 1; } } void addRef() {mcount++;} // 添加引用计数 int delRef() {return --mcount;} private: T *mptr; int mcount; }; template class CSmartPtr{ public: CSmartPtr(T *ptr = nullptr) : mptr(ptr){ mpRefCnt = new RefCnt (mptr); } // CSmartPtr(const CSmartPtr &src){ // mptr = new T(*src.mptr); // } ~CSmartPtr(){ if(0 == mpRefCnt->delRef()){ delete mptr; mptr = nullptr; } } T &operator* (){ return *mptr; } T *operator->(){ return mptr; } //重写拷贝构造 CSmartPtr(const CSmartPtr &src) :mptr(src.mptr), mpRefCnt(src.mpRefCnt) { if(mptr != nullptr){ mpRefCnt->addRef(); } } CSmartPtr & operator=(const CSmartPtr &src){ if(this == &src){ return *this; } if(mpRefCnt->delRef() == 0){ delete mptr; } mptr = src.mptr; mpRefCnt = src.mpRefCnt; mpRefCnt->addRef(); return *this; } private: T *mptr; RefCnt *mpRefCnt; }; int main(){ CSmartPtr p1(new int ); CSmartPtr p2(p1); *p1 = 20; cout << *p2; }
- shared_ptr:强智能指针 可以改变资源的引用计数
- weak_ptr:弱智能指针 不会改变资源的引用计数
- weak_ptr => shared_ptr => 资源(内存)
#include "iostream"
using namespace std;
#include "memory"
class B;
class A{
public:
A() {cout << "A()" << endl;}
~A() {cout << "~A()" <_ptrb = pb;
pb->_ptra = pa;
cout << pa.use_count() << endl;
cout << pb.use_count() << endl;
}
打印结果: A() B() 2 2
造成new出来的资源无法释放,资源泄露。
class B;
class A{
public:
A() {cout << "A()" << endl;}
~A() {cout << "~A()" <
打印:
A()
B()
1
1
~B()
~A()
weak_ptr
无法调用,没有提供operator* operator->
解决 可以用把它提升为强智能指针
void func(){
// _ptra->testA();
shared_ptr ps = _ptra.lock(); //提升方法
if(ps != nullptr){
ps->testA();
}
}
多线程访问共享对象的线程安全问题
#include "iostream"
#include "memory"
#include "thread"
using namespace std;
class A{
public:
A() {cout << "A()" << endl;}
~A() {cout << "~A()" <testA();
}
int main(){
A *p = new A();
thread t1(handler01, p);
delete p;
t1.join();
}
//打印
A()
~A()
非常好用的方法!
这样非常不好 因为A对象都已经释放了,但是还是可以访问。所以q在访问A对象的时候,需要侦测一下A对象是否存活。
解决
#include "iostream"
#include "memory"
#include "thread"
using namespace std;
class A{
public:
A() {cout << "A()" << endl;}
~A() {cout << "~A()" <testA();
} else {
cout << "A对象已经析构, 不能在访问" <
//打印
A()
~A()
A对象已经析构, 不能在访问



