C++中的智能指针-LMLPHP
智能指针是在 C + + 14 C++14 C++14中新引入的,所以在编译的时候最好加入 " − s t d = c + + 14 " "-std=c++14" "std=c++14"的编译选项。智能指针一共有两种,分别是 u n i q u e _ p t r unique\_ptr unique_ptr s h a r e d _ p t r shared\_ptr shared_ptr

u n i q u e _ p t r unique\_ptr unique_ptr

u n i q u e _ p t r unique\_ptr unique_ptr可以使用 m a k e _ u n i q u e make\_unique make_unique来生成:

  template<typename _Tp, typename... _Args>
    inline typename _MakeUniq<_Tp>::__single_object
    make_unique(_Args&&... __args)
    { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }

可以看出 m a k e _ u n i q u e make\_unique make_unique是一个模板函数,将返回一个 _ T p \_Tp _Tp类型的指针,也就是假设有一个 p o i n t point point类:

struct point
{
	int x, y;
	point(int x, int y)
	{
		this->x = x;
		this->y = y;
	}
};

然后声明一个指针:

std::unique_ptr<point> x = make_unique<point>(3, 5);

x x x为一个指向 p o i n t ( 3 , 5 ) point(3,5) point(3,5)的指针,然而由于其" u n q i u e unqiue unqiue"的特性, x x x不可被拷贝构造以及拷贝赋值,在源码里,其拷贝构造以及拷贝赋值被定义成以下的形式:

unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;

C + + C++ C++中,“ = d e l e t e = delete =delete"是一种特殊的函数声明方式,用于禁用或删除某个函数的默认实现。当一个函数被声明为” = d e l e t e = delete =delete"时,编译器将不会生成该函数的默认实现,并且在尝试调用该函数时会引发编译错误。
然而,有的时候需要将 x x x指向的内存转给其他指针,那么这个时候,只有唯一的一种方法,就是:

auto y = std::move(x);
//or std::unique_ptr<point> y = std::move(x);

s h a r e d _ p t r shared\_ptr shared_ptr

s h a r e d _ p t r shared\_ptr shared_ptr不同于 u n i q u e _ p t r unique\_ptr unique_ptr,其可以通过拷贝赋值给其他指针,以下分别是其拷贝构造以及拷贝赋值函数。

shared_ptr& operator=(const shared_ptr& _Right) noexcept
		{	// assign shared ownership of resource owned by _Right
		shared_ptr(_Right).swap(*this);
		return (*this);
		}
shared_ptr(const shared_ptr& _Other) noexcept
		{	// construct shared_ptr object that owns same resource as _Other
		this->_Copy_construct_from(_Other);
		}

也就是说, s h a r e d _ p t r shared\_ptr shared_ptr可以通过以下方式构造:

std::shared_ptr<point> x = make_shared<point>(3, 5);
auto y = x;
auto z(x);

同时可以通过 u s e _ c o u n t use\_count use_count方法统计一块相同的内存被几个指针共享:

cout << x.use_count() << endl;

共享指针有以下几个 t r i c k trick trick

  1. 当共享指针被拷贝构造或者拷贝赋值的时候,指向的内存才算被共享了一次,所以上面的那段代码输出的结果为 3 3 3,然而如果是进行浅拷贝的话,不算做一次共享:
auto y = std::move(x);
cout<<y.use_count()<<x.use_count<<endl;
//该结果为3 0
  1. 如果是传入函数并且打印 u s e _ c o u n t use\_count use_count,也有以下两种情况。
void func(std::shared_ptr<point> x)
{
	cout << x.use_count() << endl;
}
int main(void)
{
	std::shared_ptr<point> x = make_shared<point>(3, 5);
	auto y = x;
	auto z(x);
	cout << x.use_count() << endl;
	func(std::move(x));//这个右值引用如果给一个左值里面就空了
	cout << x.use_count() << endl;
}
//本结果为
//3 3 0
//如果调用x的其他属性会报段错误。
void func(std::shared_ptr<point>&& x)
{
	cout << x.use_count() << endl;
}
int main(void)
{
	std::shared_ptr<point> x = make_shared<point>(3, 5);
	auto y = x;
	auto z(x);
	cout << x.use_count() << endl;
	func(std::move(x));//这个右值引用如果给一个左值里面就空了
	cout << x.use_count() << endl;
}
//这个结果为3 3 3

如果不按右值引用传入:

void func(std::shared_ptr<point> x)
{
	cout << x.use_count() << endl;
}
int main(void)
{
	std::shared_ptr<point> x = make_shared<point>(3, 5);
	auto y = x;
	auto z(x);
	cout << x.use_count() << endl;
	func(x);//这个右值引用如果给一个左值里面就空了
	cout << x.use_count() << endl;
}
//这个结果是3 4 3
10-18 16:43