PS:智能指针简单应用看这里 http://t.csdn.cn/qN7IK
1.智能指针的介绍
在C++中,智能指针有三个版本,分别为:
auto_ptr unique_ptr shared_ptr
这三个版本的智能指针中,shared_ptr最为完善,auto_ptr基本上没有太大用处,unique_ptr的使用场景并不多。对于智能指针来说,需要实现RAII和重载operator*和operator->,使它具有像指针一样的行为。
2.智能指针分析
2.1 auto_ptr版本
auto_ptr简单实现:
template<class T>
class Auto_ptr
{
public:
//管理权转移 auto_ptr
Auto_ptr(T* ptr)
:_ptr(ptr)
{}
Auto_ptr(Auto_ptr<T>& ptr)
:_ptr(ptr._ptr)
{
ptr._ptr=nullptr;
}
T& operator=(const T& ptr)
{
if (this != &ptr)
{
if (_ptr)
{
cout << "Delete:" << _ptr << endl;
delete _ptr;
}
_ptr = ptr._ptr;
ptr._ptr = nullptr;
}
return *this;
}
//析构函数需要写重载,不同常见需要不同析构函数
/*~Auto_ptr()
{
if (_ptr)
{
delete _ptr;
}
}*/
T& operator*()
{
return *this;
}
T* operator->()
{
return this;
}
private:
T* _ptr=nullptr;
};
由于auto_ptr支持拷贝构造,为了确保指针所有者唯一,这里转移了所有权,转移所有权之后,导致了被拷贝的为空了,这是一大缺点,导致auto_ptr被遗弃。
2.2.unique_ptr的使用
template<class T>
class Unique_ptr
{
public:
Unique_ptr(T* ptr)
:_ptr(ptr)
{}
Unique_ptr(Auto_ptr<T>& ptr) = delete;
T& operator=(const T& ptr) = delete;
/*~Auto_ptr()
{
if (_ptr)
{
delete _ptr;
}
}*/
T& operator*()
{
return *this;
}
T* operator->()
{
return this;
}
private:
T* _ptr = nullptr;
};
unique_ptr的底层直接没有使用拷贝构造和赋值重载,导致它只能使用在不需要拷贝构造和复制重载的场景上,所以unique_ptr的缺点为unique_ptr 不共享它的指针。 它无法复制到其它unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL) 算法。 只能移动unique_ptr 。 这意味着,内存资源所有权将转移到另一 unique_ptr,并且原始 unique_ptr 不再拥有此资源。
2.3 shared_ptr的使用
template<class T>
class Shared_ptr
{
public:
Shared_ptr(T* ptr=nullptr)
:_ptr(ptr)
,_Pcount(new int(1))
{
;
}
void Release()
{
if (--(*_Pcount) == 0)
{
cout << "Delete:" << _ptr << endl;
delete _ptr;
delete _Pcount;
}
}
~Shared_ptr()
{
Release();
}
Shared_ptr(Smart_ptr<T>& ptr)
:_ptr(ptr)
{
(*_Pcount)++;
ptr = nullptr;
}
Shared_ptr& operator=(Smart_ptr& ptr)
{
if (_ptr == ptr._ptr)
return *this;
Release();
--(*_Pcount);
_ptr = ptr._ptr;
_Pcount = ptr._Pcount;
*_Pcount++;
return *this;
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
private:
T* _ptr;
int* _Pcount;
};
在unique_ptr的基础上,新增加了一个版本,为shared_ptr版本。
基本原理:就是记录对象被引用的次数,当引用次数为 0 的时候,也就是最后一个指向该对象的共享指针析构的时候,共享指针的析构函数就把指向的内存区域释放掉。
特点:它所指向的资源具有共享性,即多个shared_ptr可以指向同一份资源,并在内部使用引用计数机制来实现这一点。
共享指针内存:每个 shared_ptr 对象在内部指向两个内存位置:
- 指向对象的指针;
- 用于控制引用计数数据的指针。
当新的 shared_ptr 对象与指针关联时,则在其构造函数中,将与此指针关联的引用计数增加1。
当任何 shared_ptr 对象超出作用域时,则在其析构函数中,它将关联指针的引用计数减1。如果引用计数变为0,则表示没有其他 shared_ptr 对象与此内存关联,在这种情况下,它使用delete函数删除该内存。
shared_ptr像普通指针一样使用,可以将*和->与 shared_ptr 对象一起使用,也可以像其他 shared_ptr 对象一样进行比较。
但是,对于shared_ptr来说,依然有一个缺点,如果是循环引用,那么将会出现bug,这时候就需要使用weak_ptr.
2.4 weak_ptr使用
weak_ptr
是一个弱引用的智能指针,它可以与shared_ptr
一起使用。weak_ptr
不会增加所管理的对象的引用计数,因此它不会影响对象的生命周期。可以通过weak_ptr
的lock()
成员函数来获取一个指向所管理的对象的shared_ptr
。
3.总结:
3.1 智能指针原理:
智能指针解决问题的思想:将常规指针进行包装,当智能指针对象过期时,让它的析构函数对常规指针进行内存释放。
auto_ptr(C++98的方案,C++11已经废弃):采用所有权模式,对于特定的对象,只能有一个智能指针可拥有它,这样只有拥有对象的智能指针的析构函数会删除该对象。然后,让赋值操作转让所有权。
unique_ptr(替代 auto_ptr):也是采用所有权模式,实现独占式拥有或严格拥有概念,保证同一时间内只有一个智能指针可以指向该对象。
shared_ptr:采用引用计数实现共享式拥有概念。多个智能指针可以指向相同对象,该对象和其相关资源会在最后一个引用被销毁时候释放。它使用引用计数来表明资源被几个指针共享。例如,赋值时,计数将加 1,而指针过期时,计数将减 1。仅当最后一个指针过期时,才调用 delete。
weak_ptr:该类型指针通常不单独使用(没有实际用处),只能和 shared_ptr 类型指针搭配使用。weak_ptr 类型指针并不会影响所指堆内存空间的引用计数,可以用来解决循环引用问题。
3.2 使用场景文章来源:https://www.toymoban.com/news/detail-686715.html
如果在程序中使用new 从堆(自由存储区)分配内存,等到不再需要时,应使用 delete 将其释放,如果忘记释放,则会产生内存泄露。C++ 引入了智能指针, 以帮助自动完成这个过程。智能指针是行为类似于指针的类对象。如果程序要使用多个指向同一个对象的指针,应该选择shared_ptr;如果程序不需要多个指向同一个对象的指针,则可以使用unique_ptr;如果使用new [] 分配内存,应该选择 unique_ptr;如果函数使用new 分配内存,并返回指向该内存的指针,将其返回类型声明为 unique_ptr 是不错的选择。文章来源地址https://www.toymoban.com/news/detail-686715.html
到了这里,关于C++--深度理解智能指针的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!