C++11--智能指针详解及实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/i_chaoren/article/details/82586456

1、基础概念

智能指针的一种通用实现技术是使用引用计数。智能指针类将一个计数器与智能指针指向的对象相关联,用来记录有多少个智能指针指向相同的对象,并在恰当的时候释放对象

每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,引用计数加1;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。

下图是shared_ptr的内存模型:

由图中可以看到,实际上引用计数、自定义销毁等都不是直接存储在shared_ptr中,而是通过一个指针指向的一个控制块存储的,控制块是动态分配的内存 。

下面是用类模板简单实现shared_ptr.

#include <iostream>
using namespace std;

template<typename T>
class SmartPointer {
private:
	T* p_;
	size_t* count_;
public:
	SmartPointer(T* ptr = nullptr) : p_(ptr) {
		if (p_) {
			count_ = new size_t(1);
		}
		else {
			count_ = new size_t(0);
		}
	}

	SmartPointer(const SmartPointer& ptr) {
		p_ = ptr.p_;
		count_ = ptr.count_;
		(*count_)++;
	}

	SmartPointer& operator=(const SmartPointer& ptr) {
		if (p_ == ptr.p_) {
			return *this;
		}

		if (p_) {
			if (--(*count_) == 0) {
				delete p_;
				delete count_;
			}
		}

		p_ = ptr.p_;
		count_ = ptr.count_;
		(*count_)++;
		return *this;
	}

	~SmartPointer() {
		if (--(*count_) == 0) {
			delete p_;
			delete count_;
		}
	}

	size_t use_count() {
		return *count_;
	}
};

int main() {
	SmartPointer<int> sp1(new int(10));
	SmartPointer<int> sp2(sp1);
	SmartPointer<int> sp3(new int(20));
	sp2 = sp3;
	std::cout << sp1.use_count() << std::endl;
	std::cout << sp3.use_count() << std::endl;
}

2、智能指针带来的性能影响

1)shared_ptr的尺寸是裸指针的两倍。 

2)会带来控制块的开销。

3)引用计数的递增和递减是原子操作,原子操作一般都比非原子操作慢。

3、使用weak_ptr解决shared_ptr的循环引用。

 解决方案:将类A,B中的shared_prt改为weak_ptr即可,weak_ptr不会增加shared_ptr的引用计数

class B;
class A {
public:
   weak_ptr<B> p;
   //shared_ptr<B> p;
};
class B {
public:
   weak_ptr<A> p;
   //shared_ptr<A> p;
};
int main() {
  while (true) {
     shared_ptr<A> pa(new A());
     shared_ptr<B> pb(new B());
      pa->p = pb;
      pb->p = pa;
   }
  return 0;
}

参考文章:

1. https://www.cnblogs.com/wxquare/p/4759020.html

2. https://segmentfault.com/a/1190000006860811

猜你喜欢

转载自blog.csdn.net/i_chaoren/article/details/82586456