您的位置:首页 > 房产 > 家装 > 智能小程序入口_网页设计费_找精准客户的app_厦门百度整站优化服务

智能小程序入口_网页设计费_找精准客户的app_厦门百度整站优化服务

2025/1/13 6:17:14 来源:https://blog.csdn.net/klausur31/article/details/145087155  浏览:    关键词:智能小程序入口_网页设计费_找精准客户的app_厦门百度整站优化服务
智能小程序入口_网页设计费_找精准客户的app_厦门百度整站优化服务

1.资源泄漏问题

C++并没有垃圾回收机制(gc),这使得我们使用new或者malloc等开出空间后,需要释放资源。

但是当我们忘记释放资源,或者有异常安全问题时。就会导致资源没有被回收,我们又不能继续使用这块资源,终止导致资源泄漏问题

2.避免资源泄漏问题的方法

2.1我们可以良好的设计规范,申请资源结束后释放资源;遇到异常安全问题,我们可以使用异常重抛出解决资源泄漏。

2.2 利用RAII的思想或者智能指针来管理资源。

3.智能指针

3.1RAII

RAII计数是一种利用对象生命周期来控制程序资源的一种技术。其包括①在构造对象时获取资源②在析构对象时,释放资源。

它的好处在于,我们不需要显示的手动释放资源,在对象生命周期结束后,会自动调用其析构函数,达到释放资源的目的。

3.2智能指针

智能指针就是利用上述RAII的思路设计的。当然我们还需要加入operator->和operator*,才能向指针一样使用它。

// 使用RAII思想设计的SmartPtr类
template<class T>
class SmartPtr {
public:SmartPtr(T* ptr = nullptr): _ptr(ptr){}~SmartPtr(){if(_ptr)delete _ptr;}T& operator*() {return *_ptr;}T* operator->() {return _ptr;}
private:T* _ptr;
};

但是以上的智能指针存在一个问题,当我们将一个指针同时交给两个不同的对象管理时,就会将这块指针管理的空间delete掉两次,会报错。接下来就是C++的解决方案历程了

3.3 auto_ptr(C++98)

在c++98的auto_ptr的设计中就提出了管理权转移的思路。即当我使用拷贝构造,或者赋值重载运算的时候,就将我的指针传递给另一个对象,将我架空变为nullptr。

 template<class T>class auto_ptr{public:auto_ptr(T* ptr):_ptr(ptr){}auto_ptr(auto_ptr<T>& sp):_ptr(sp._ptr){// 管理权转移sp._ptr = nullptr;}auto_ptr<T>& operator=(auto_ptr<T>& ap){// 检测是否为自己给自己赋值if (this != &ap){// 释放当前对象中资源if (_ptr)delete _ptr;// 转移ap中资源到当前对象中_ptr = ap._ptr;ap._ptr = NULL;}return *this;}~auto_ptr(){if (_ptr){delete _ptr;}// 像指针一样使用T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};
}

我们不推荐使用

3.4 unique_ptr(C++11)

unique_ptr实现的一种防拷贝构造和赋值重载的思路,即在类设计时就将拷贝构造和赋值重载delete掉,其余实现与上面的同。

unique_ptr(const unique_ptr<T>& sp) = delete;
unique_ptr<T>& operator=(const unique_ptr<T>& sp) = delete;

但是他只是禁止了,还是没有解决问题

3.5 shared_ptr(C++11)

shared_ptr即共享指针,它的解决思路是引用了计数。 首先为了解决计数问题,在构造的时候就会new一块地址存储int计数器。当我们拷贝构造或者是赋值重载的时候,也要将计数器一块传给新大小,并将计算器++。同时当我们delete掉一个对象时,先--计数器,然后当计数器==0,时才会触发delete。

为了线程安全,因为++或者--的过程实际上有三步骤,重寄存器中拿出数据,++数据,存入数据,当我们有两块线程同时运行时,就会导致线程不安全问题,说以我们还要引入线程锁。在++或者--之前先上锁,之后解锁。我们在拷贝构造和赋值重载时也需要将线程锁一块传给新对象。

template <class T>
class shared_ptr {
public:shared_ptr(T* ptr):_ptr(ptr),_pcont(new int(1)),_mtx(new std::mutex){}shared_ptr(const shared_ptr<T>& sp):_ptr(sp._ptr),_pcont(sp._pcont),_mtx(sp._mtx)  //拷贝构造时,将ptr,计数地址,锁一块传过去,然后addcont{	addcont();}void addcont() {_mtx->lock();   //上锁(*_pcont)++;_mtx->unlock();}int get_cont(){return *_pcont;}void release() {_mtx->lock();bool flag = false;if (--(*_pcont) == 0 && _ptr) {delete _ptr;delete _pcont;flag = true;std::cout << "自动回收成功" << std::endl;}_mtx->unlock();if (flag) {delete _mtx;}}~shared_ptr() {   //利用RAII实现资源回收机制release();}T& operator*() {return *_ptr;}T* operator->() {return _ptr;}T* getptr() const{return _ptr;}shared_ptr<T>& operator=(const shared_ptr<T>& sp) {//先处理原有数据if (this != &sp) {if (--(*_pcont) == 0) {release();}_ptr = sp._ptr;_pcont = sp._pcont;_mtx = sp._mtx;addcont();}return *this;}private:T* _ptr;int* _pcont;   //利用计数解决共享问题std::mutex* _mtx;   //解决多线程的计数不安全问题
};

但是shared_ptr也并不完善,当我们遇到循环引用问题时就会触发bug。

3.6weak_ptr(C++11专门解决循环引用问题)

当我们设计一个双链表,并用智能指针保存链表的对象中的_prev和_pnext时就出现问题。

当我本身创建时就会将计数器初始化为1,当我将我的ptr交给另一个链表对象的prev时就会++,将计数器加到2.但是当我需要删除链表的一个节点时,我只能将计数器减到1,如果想要减到0,那么我需要删除另一个节点的prev,另个节点的prev的删除需要删除另一个对象,但是另一个对象的计计数器也是2,导致了一个循环引用的问题。

为了解决这个问题,C++就提出了weak_ptr,弱指针,其实际上就是对shared_ptr的托管,将其用shared_ptr拷贝构造和赋值重载,这样就不会导致shared对象利用shared构造时的++问题。

template<class T>
class weak_ptr {   //弱指针解决shared指针的循环引用问题weak_ptr(const shared_ptr<T>& sp):_ptr(sp.getptr()){}weak_ptr<T>& operator=(const shared_ptr<T>& sp) {_ptr = sp.getptr();return *this;}T* operator->() {return _ptr;}T& operator*() {return *_ptr;}private:T* _ptr;
};

4.智能指针的定制删除器

在shared_ptr的库函数实现时,其默认也是对new的单个对象进行的delete,当我们是new[]时或者是其他的malloc,fopen出的空间时,就需要在传入一个自己定制的删除器仿函数实现删除。

shared_ptr<int> array((int*)malloc(sizeof(int) * 4), [](void* x) {free(x);});
shared_ptr<FILE> a(fopen("clasiu.txt", "w"), [](FILE* f) {fclose(f); })
shared_ptr<int> array1(new int[10] , [](int* x){deletep[] x;})

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com