深入掌握C++智能指针_深入掌握c++智能指针 大秦坑王-CSDN博客
C++11 - 右值引用_大秦坑王 右值引用+引用折叠原理-CSDN博客
一、基本原理
智能指针的基本原理,就是利用栈上的对象出作用域会自动析构这么一个特点,把资源释放的代码全部放在这个析构函数中执行,就达到了所谓的智能指针。
template<typename T>
class CSmartPtr
{
public:
CSmartPtr(T *ptr = nullptr) :mptr(ptr) {}
~CSmartPtr() { delete mptr; }
private:
T *mptr;
};
int main()
{
CSmartPtr<int> ptr(new int);
/*其它的代码...*/
/*由于ptr是栈上的智能指针对象,不管是函数正常执行完,还是运行过程中出现
异常,栈上的对象都会自动调用析构函数,在析构函数中进行了delete
操作,保证释放资源*/
return 0;
}
上面这段代码就是一个非常简单的智能指针,主要用到了这两点:
1)智能指针体现在把裸指针进行了一次面向对象的封装,在构造函数中初始化资源地址,在析构函数中负责释放资源
2)利用栈上的对象出作用域自动析构这个特点,在智能指针的析构函数中保证释放资源
所以,智能指针一般都是定义在栈上的,曾经有一个面试问题,问“能不能在堆上定义智能指针?”,如这段代码CSmartPtr *p = new CSmartPtr(new int);大家应该能看出来,这里定义的p虽然是智能指针类型,但它实质上还是一个裸指针,因此p还是需要进行手动delete,又回到了最开始裸指针我们面临的问题。
二、智能指针要做到和裸指针相似,还得提供裸指针常见的*和->两种运算符的重载函数,使用起来才真正的和裸指针一样
template<typename T>
class CSmartPtr
{
public:
CSmartPtr(T *ptr = nullptr) :mptr(ptr) {}
~CSmartPtr() { delete mptr; }
T& operator*() { return *mptr; }
const T& operator*()const { return *mptr; }
T* operator->() { return mptr; }
const T* operator->()const { return mptr; }
private:
T *mptr;
};
int main()
{
CSmartPtr<int> ptr(new int);
*ptr = 20;
// -> 底层实际是 ( ptr.operator->() )->test(); test() 是方法
cout << *ptr << endl;
return 0;
}
三、智能指针的构造函数
int main()
{
CSmartPtr<int> ptr1(new int);
CSmartPtr<int> ptr2(ptr1);
return 0;
}
这个main函数运行,代码直接崩溃,问题出在默认的拷贝构造函数做的是浅拷贝,两个智能指针都持有一个new int资源,ptr2先析构释放了资源,到ptr1析构的时候,就成了delete野指针了,造成程序崩溃。所以这里引出来智能指针需要解决的两件事情:
怎么解决智能指针的浅拷贝问题
多个智能指针指向同一个资源的时候,怎么保证资源只释放一次,而不是每个智能指针都释放一次,造成代码运行不可预期的严重后果
之前的深拷贝构造函数,在智能指针中不行,因为是重新开辟了一块资源给ptr2,ptr1和ptr2是两块内存,可是用户人为是ptr1和ptr2指向同一块内存。
将怎么解决浅拷贝问题可以分为 不带引用计数的智能指针和带引用计数的智能指针
C++库中提供的不带引用计数的智能指针主要包括:auto_ptr,scoped_ptr,unique_ptr。
使用 explicit 关键字可以避免一些意外的隐式类型转换,提高代码的安全性和可读性。通常情况下,如果构造函数只接受一个参数,并且不希望它被隐式调用,就应该将其声明为 explicit。
四、auto_ptr,scoped_ptr,unique_ptr
一、auto_ptr在拷贝构造中,将原有的智能指针置为nullptr,然后将对象赋值给新的智能指针。


二、scoped_ptr 将拷贝构造函数和赋值操作删除或私有化
template<class T> class scoped_ptr // noncopyable
{
private:
T * px;
/*
私有化拷贝构造函数和赋值函数,这样scoped_ptr的智能指针
对象就不支持这两种操作,从根本上杜绝浅拷贝的发生
*/
scoped_ptr(scoped_ptr const &);
scoped_ptr & operator=(scoped_ptr const &);
typedef scoped_ptr<T> this_type;
/*
私有化逻辑比较运算符重载函数,不支持scoped_ptr的


2112

被折叠的 条评论
为什么被折叠?



