1 智能指针是什么?智能指针的原理
a smart pointer is a class template that you declare on the stack, and initialize by using a raw pointer that points to a heap-allocated object. After the smart pointer is initialized, it owns the raw pointer. This means that the smart pointer is responsible for deleting the memory that the raw pointer specifies. The smart pointer destructor contains the call to delete, and because the smart pointer is declared on the stack, its destructor is invoked when the smart pointer goes out of scope, even if an exception is thrown somewhere further up the stack.
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??Smart pointers (Modern C++) | Microsoft Docs
智能指针是一个模板类,这个类的构造函数传入一个普通的指针,析构函数释放传入的指针。智能指针上的类都是栈上的对象,所以当函数或者程序结束时就会自动释放。
2 常用智能指针
? ? ? ??unique_ptr实现独占式拥有或严格拥有概念,保证同一时间内只有一个智能指针可以指向该对象。unique_ptr支持不可复制,赋值,但可以move()转移对象的所有权,局部变量的返回值除外。
智能指针实现重点:
template<class T>
class myUniquePtr{
private:
T *m_ptr;
public:
explicit myUniquePtr(T* ptr= nullptr):m_ptr(ptr) {}
~myUniquePtr(){
if(m_ptr)
delete m_ptr;
}
myUniquePtr(const myUniquePtr&) = delete;
myUniquePtr& operator=(const myUniquePtr &p) =delete;
T* operator*() const{return *m_ptr;}
T& operator->() const{return m_ptr;}
myUniquePtr(myUniquePtr &&p):m_ptr(p.m_ptr){p.m_ptr= nullptr;}
myUniquePtr& operator=(myUniquePtr &&p){
swap(*this,p);//采用swap函数实现移动赋值
return *this;
}
explicit operator bool() const {return m_ptr;}
void reset(T* q = nullptr){
if(q!=m_ptr){
if(m_ptr)
delete m_ptr;
m_ptr = q;
}
}
T* release(){
T* res = m_ptr;
m_ptr = nullptr;
return res;
}
T* get(){
return m_ptr;
}
void swap(myUniquePtr &p){
std::swap(m_ptr,p.m_ptr);
}
};
? ? ? ? shared_ptr 是引用计数型(reference counting)智能指针,几乎所有的实现都采用在堆(heap)上放个计数值(count)的办法。具体来说,shared_ptr<Foo> 包含两个成员,一个是指向 Foo 的指针 ptr,另一个是 ref_count 指针,指向堆上的 ref_count 对象,ref_count 对象有多个成员。
? ? ? ? shared_ptr是否线程安全,如何实现线程安全?
? ? ? ? 结论:多个线程同时读同一个shared_ptr对象是线程安全的,但是如果是多个线程对同一个shared_ptr对象进行读和写,则需要加锁。
? ? ? ? 为什么尽可能使用make_shared()?? ? ??
????????为了节省一次内存分配,原来 shared_ptr<Foo> x(new Foo); 需要为 Foo 和 ref_count 各分配一次内存,现在用 make_shared() 的话,可以一次分配一块足够大的内存,供 Foo 和 ref_count 对象容身。
- weak_ptr? ? ? ? ? ? ? ? ?
? ? ? ? shared_ptr存在互相引用形成环的问题,这样子两个指针指向的内存都无法释放,需要手动打破循环引用或者是使用weak_ptr。weak_ptr是一个弱引用,只引用不计数。如果一块内存被shared_ptr和weak_ptr同时引用,当所有shared_ptr析构之后,不管还有没有weak_ptr应用该内存,内存都会被释放掉。所以weak_ptr不保证其指向的内容是有效的,在使用前需要检查weak_ptr是否为空指针。
参考资料?
|