智能指针

之前在《Effective C++》中看了一些关于智能指针的内容,今天想在这里结合《C++ Primer Plus》以及自己的一些想法再复习一下,就算是巩固自己的这部分的知识。毕竟智能指针对于C++来说还是挺重要的。

1 . 问题的引出,我们先来看下边的一个程序段。

void remodel(std::string& str) {

	std::string* ps = new std::string(str);
	str = ps;
	return;
}
我们在函数中,向“堆”申请了一块内存。但是在函数调用结束后,并没有手动将ps释放掉。因此,我们可以在return之前,将ps给return掉。

void remodel(std::string& str) {

	std::string* ps = new std::string(str);
	
	/*
		异常处理代码
	*/

	str = *ps;
	delete ps;
	return;
}

这样,我们手动释放了ps。并且在申请内存之后,假设添加了一段异常处理的程序,如果New失败了,后边的代码也不会执行,但是会导致内存泄漏。ps是没有办法主动去将自己给释放掉的,我们明白的是,常规的类是有自己的析构函数的,在使用结束后,会主动调用析构函数来释放自己。但是ps仅仅是一个常规指针,不是一个类,没有自己的析构函数。基于这一点,智能指针就是这样出现的。

2 . 比较常用的智能指针是:”auto_ptr“( C++98的方案,C++11摒弃,但是可以使用 )、”unique_ptr“、”shared_ptr“。这三种智能指针模板都定义了类似指针的对象,可以将New出来的地址赋给对象,智能指针过期的时候,会调用析构函数,释放内存。

3 . std::auto_ptr智能指针模板

void remodel(std::string& str) {

	std::auto_ptr ps(new std::string(str));
	str = *ps;
	return;
}
上边是std::auto_ptr的使用实例,我们只需要这样写,智能指针对象可以在过期的时候,释放内存,不再需要手动delete。

我们在查看std::auto_ptr的实现代码发现,它的用法有点类似于std::vector。例如:ps.get()返回当前指针对象,ps.release()的含义是”return wrapped pointer and give up ownership“,返回一个指针对象,并放弃所有权,ps.reset()的含义是”destroy designated object and store new pointer“,销毁指针对象,并存储新的指针(指向空)。

智能指针_第1张图片

我们在std::auto_ptr中的实现代码里还发现了“operation =”,对于“=”的重载,首先是release了右值,返回左值。也就是说,指针对象的所有权被转移。

	_Myt& operator=(_Myt& _Right) _THROW0()
		{	// assign compatible _Right (assume pointer)
		reset(_Right.release());
		return (*this);
		}
4 . std::unique_ptr智能指针模板

“ std::unique_ptr ps(new std::string(str)) ”这样的程序我们依然可以写,但是不能使用拷贝函数和赋值运算符将指针对象的控制权转移。

std::unique_ptr ps(new std::string(str));
	
	// ps为空,所有权转移到ps1上
	std::unique_ptr ps1 = std::move(ps);

	// ps1为空,所有权转移到ps2上
	std::unique_ptr ps2 = std::move(ps1);
现在我目前理解的就到现在这个层面,通过move函数充当拷贝函数或者赋值运算符来转移指针对象的所有权。

5 . std::shared_ptr智能指针模板

std::shared_ptr与前两个的区别是:前两个智能指针将指针对象的控制权进行转移的时候,是会把前一个清除掉,只允许一个智能指针控制一个指针对象。而std::shared_ptr则不会将前一个清除掉,有可能会出现好几个智能指针控制一个指针对象。当你删除掉一个的时候,不会影响其他智能指针的使用,因为声明一个std::shared_ptr,引用计数+1,调用析构函数的时候,引用计数-1,直到最后一个智能指针被删除,才会释放内存。










你可能感兴趣的:(C,/,C++)