三种C++智能指针模板---只需要这样的简解

C++智能指针模板

帮助管理动态内存分配
涉及堆内存的动态内存分配时时,总是需要记住delete,但是总会有犯错忘记而导致内存泄漏的时候.
即使没有忘记这个,也可能被异常给破坏掉。
假如有如下函数,在函数内请求动态内存,退出时delete。问题是:异常时将会内存泄漏,知道栈解退原理便知道,p指针内存被释放,可是指向的内存不会被释放
关于栈解退有些介绍.
链接: https://blog.csdn.net/Valishment/article/details/104962230.

void GetInt(int* p)
{
    
    
	p = new int;
	...
	if (one_error())
		throw();
	...
	delete p;
	return;
}

假如指针是个自动对象而不是自动变量,栈解退的时候就会调动自动对象的析构函数,从而删除指向的内存区域。
以下三种指针便是这样做的。
在头文件(memory)中

模板1.auto_ptr模板类(C++98)-------C++11摒弃

double* p0 = new double;
std::auto_ptr<double> p1(new double);
// p1 为double* 类型
//std::auto_ptr<double*> p1(new double);  错误
// p2 为double**类型
p1 = auto_ptr<double>(p0);
//这种显示转换对三种指针都有效
std::auto_ptr<Student> p2(new Student("小明", 12, "Grade 5"));

double为内置类型, Student为自定义类型。
允许通过显示转换将同样指向堆内存的指针:
问题:
两个智能指针指向同一块区域,不做处理的话就会delete同一块区域多次

std::auto_ptr<double> p1(new double);
*p1 = 10;
std::auto_ptr<double> p2 = p1;
std::cout << *p1 << *p2 << std::endl;
std::auto_ptr<double> p3;
p3 = p2;
std::cout << *p2 << *p3 << std::endl;
// p1: 我没了啊(NULL)
// p2: 内存归我了(000XXXXX)
std::auto_ptr<double> p3;
p3 = p2;
std::cout << *p2 << *p3 << std::endl;
// p2: 我怎么也没了??(NULL)
// p3: 现在归我了!!(000XXXXX)
// ....
// ....

auto_ptr模板处理这类事件的时候,就是让先前的指针变为空指针,也就是右值指针变为了NULL
在这里右值是p1和p2. 左值是被修改值,也就是p2, p3.

因此这样做有风险,C++11摒弃了,谁也不想程序在输出NULL指针时候崩溃。

模板2.unique_ptr模板类(优等生)

使用此模板同auto_ptr模板一样。
承接上文,unique_ptr在处理此类事件时候,将会禁止相互赋值

...
p2 = p1;
// 编译器说:我不同意
...
p2 = p3
// p1:活下来了

例外:
假设我们编写一个函数用来专门请求堆内存赋给一个智能指针,然后当做返回值返回。(由于返回时候,自动变量被销毁,也就是函数里的智能指针自动消失了,不会出现输出NULL指针的情况)

unique_ptr<...> GetHeap()
{
    
    
	...
	unique_ptr<...> p = new ..;
	// 快要被干掉的指针p
	// 要找个家伙继承下财产
	...
	return p;

}
unique_ptr<...> ptr1 = GetHeap();
// ptr1继承了p的遗产(允许)

代码中便是这么做的,编译器只允许这种将命不长的智能指针给其他指针用.

模板3.shared_ptr类模板(更智能)

指针赋值时,计数+1(static静态类型变量),当最后一个指针要被删除时,再释放指向的内存区域。
也就是这种指针允许多个指针指向同一块堆内存,但是只释放一次。

注意!

初始化智能指针时候,只能使用堆内存区域地址!!!
1.对于使用 new分配的时候,适用于这三种指针模板
auto_ptr 和 shared_ptr 析构函数是 delete !!! 不是 delete[] !!!
所以不能使用new [] 来初始化auto_ptr 和 shared_ptr 指针。
unique_ptr 对两种 new 都支持
::new 和 delete配对, new[] 和 delete[] 配对。

猜你喜欢

转载自blog.csdn.net/Valishment/article/details/105149803