智能指针
unique_ptr
unique_ptr持有对对象的独有权,同一时刻只能有一个unique_ptr指向对象(通过禁止拷贝语义,只有移动语义来实现)
生命周期:从创建开始,直到离开作用域
离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)
unique_ptr实际是类模板,只不过是禁用了拷贝构造函数、赋值运算符=
重写了移动拷贝构造、->符号、*符号
独占指针的手工实现
/*
手工实现独占指针
*/
/*
unique_ptr特性
1. 独享所有权
2. 重置对象 reset()
3. 对象不可复制,不能通过=号进行复制
4. 通过std::move转移对象所有权
5. 释放关联指针release()
6. get()仅仅返回关联指针(强制delete该返回指针后,独占指针在销毁时会出错-段错误)
*/
#pragma once
#include <stdio.h>
#include <iostream>
using namespace std;
template<typename T>
class SmartPointer
{
private:
public:
//构造函数
SmartPointer(T* ptr_ = nullptr): m_ptr(ptr_){}
//支持移动拷贝构造
SmartPointer(SmartPointer &&p) noexcept : m_ptr(p.m_ptr)
{
cout << "移动拷贝" << endl;
p.m_ptr = nullptr;
}
//禁用拷贝构造函数
SmartPointer(const SmartPointer &ptr_) = delete;
//析构函数
~SmartPointer()
{
if (m_ptr)
{
delete m_ptr;
m_ptr = nullptr;
}
}
//重载->符号
T* operator->() const noexcept{return m_ptr;}
//重载 * 符号
T& operator* () const noexcept{return *m_ptr;}
//禁用赋值运算符
SmartPointer &operator = (const SmartPointer &p) = delete;
//释放智能指针地址
T* release() noexcept{
T *res = m_ptr;
m_ptr = nullptr;
return res;
}
//将托管指针重置为传入的指针
void reset(T* p = nullptr) noexcept{
std::swap(m_ptr, p);
delete p;
}
//swap
void swap(SmartPointer &p) noexcept{
std::swap(m_ptr, p.m_ptr);
}
//获取被管理对象的指针
T* get(){
return m_ptr;
}
//存放智能指针
T* m_ptr;
};
shared_ptr
共享指针,共享指针可以实现多个智能指针指向相同对象,使用计数机制来表明资源被几个指针共享,当我们release时,当前指针会释放资源所有权,计数-1。当计数为0时,资源会被释放。
/*
手动实现shared_ptr共享指针
*/
/*
共享指针
1. 每使用一次,内部引用计数加1
2. 每析构一次,内部引用计数减1
3. 引用计数减为0时自动释放原生指针所指向的内存
*/
#pragma once
#include <stdio.h>
#include <iostream>
using namespace std;
template <typename T>
class Shared_ptr
{
private:
//引用计数
int *count;
//指针
T* _ptr;
public:
//构造函数
Shared_ptr():count(0), _ptr((T*)0){}
//从原生指针构造
Shared_ptr(T* p):count(new int(1)), _ptr(p){}
//拷贝构造函数,引用计数器+1,让该对象的指针指向形参对象的指针
Shared_ptr(Shared_ptr<T>& other):count(&(++ *other.count)), _ptr(other._ptr){}
//重载->
T* operator->(){return _ptr;}
//重载*
T& operator*() {return *_ptr;}
//重载 =
//如果原来shared_ptr已经有对象,则让其引用次数减1并判断引用是否为0(是否调用delete)
//然后将新的对象引用次数加1
Shared_ptr<T>& operator= (Shared_ptr<T>& other)
{
//如果是自己赋给自己,则直接返回
if (this == &other)
return *this;
//计数器加1
++*other.count;
if (this->_ptr && 0 == --*this->count)
{
delete count;
delete _ptr;
cout << "delete ptr = " << endl;
}
this->_ptr = other._ptr;
this->count = other.count;
return *this;
}
//析构函数,使引用次数减一并判断引用是否为0(是否调用delete)
~Shared_ptr()
{
//判断ptr是否为空,并且count--后是否为0
if (_ptr && --*count == 0)
{
delete count;
delete _ptr;
cout << "delete ptr ~" << endl;
}
}
//返回引用次数
int use_count(){return *count;}
};
weak_ptr
weak_ptr是为配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,他可以从一个shared_ptr或另一个weak_ptr对象构造,他的构造和析构不会引起引用计数的增加或减少。没有重载*和->但可以使用lock获得一个可用的shared_ptr对象
weak_ptr的使用更为复杂一点,他可以指向shared_ptr指针指向的对象内存,却并不拥有该内存,而使用weak_ptr成员lock,则可返回其指向内存的一个shared_ptr对象,且在所指对象内存已经无效时,返回指针空值nullptr
使用例程
void check(weak_ptr<int> &wp)
{
shared_ptr<int> sp = wp.lock(); // 转换为shared_ptr<int>
if (sp != nullptr)
{
cout << "still " << *sp << endl;
}
else
{
cout << "pointer is invalid" << endl;
}
}
int main()
{
shared_ptr<int> sp1(new int(22));
shared_ptr<int> sp2 = sp1;
weak_ptr<int> wp = sp1; // 指向shared_ptr<int>所指对象
cout << "count: " << wp.use_count() << endl; //打印计数器
cout << *sp1 << endl; // 22
cout << *sp2 << endl; // 22
check(wp); // still 22
sp1.reset();
cout << "count: " << wp.use_count() << endl;
cout << *sp2 << endl; // 22
check(wp); // still 22
sp2.reset();
cout << "count: " << wp.use_count() << endl;
check(wp); // pointer is invalid
return 0;
}