smartPointer
引用
c++ 11:
- std::unique_ptr
c++ 14:
- std::make_unique
前言
正常的指针如果是通过new或者malloc方式还需要额外的手动释放,delect或free。
智能指针的作用是防止忘记调用delete释放内存和程序异常的进入catch块忘记释放内存。另外指针的释放时机也是非常有考究的,多次释放同一个指针会造成程序崩溃,这些都可以通过智能指针来解决。
智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。
智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏。使用智能指针可以很大程度上的避免这个问题,因为智能指针是一个类,当超出了类的实例对象的作用域时,会自动调用对象的析构函数,析构函数会自动释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。
声明方式:std::unique_ptr<type> typename{}
,
比如std::unique_ptr<int> ptra{std::make_unique<int> (150)}
转到定义看到:
能看到是用class写的,配合上模板。
正文
智能指针之所以智能,肯定会与传统指针有区别。
no1 []
比如说,传统指针无论大小,都可以用[]方式访问,但是智能指针就不行了。
1 | int main(){ |
当然很大程度上单个int不被认作为’数组‘。
传统指针需要通过int *p = new int[5]
,这样才能严格算一个数组。
那么智能指针也不例外,需要用到[],即std::unique_ptr<int[]> intP{new int[]{0}};
能够看到是合法有效的。
no2 =
传统指针之间可以套娃,多个指针指向一片内存区域
1 | int *a = new int; |
可以看到指针a由我们人为new了一块内存地址,紧接着其他指针都指向指针a的地址,但是如果a被释放了,那么其他指针就有可能成为野指针,是一种非常不妙的情况。除非特殊需求,一般也是会尽量避免这种写法。
而智能指针则不允许多个只能指针指向一块区域(简单说就是智能指针a不能赋值给智能指针b)
1 | std::unique_ptr<int> intP{ new int }; |
编译器自然而然的给出了错误。
但是有一说一,强转还是很骚的,比如说:
1 | int *a = new int; |
通过这种强转的方法,编译器也没有给出错误和警告。
当然这种假象让两个智能指针指向同一块内存也就是图一乐。
我们能想到的委员会也早想到了,所以每个版本的特性都特别重要。
no3 c++14初始化
c++14之后,在初始化的时候有新增了一种方式std::unique_ptr<int> intP { std::make_unique<int>() }
std::unique_ptr<int[]> intP { std::make_unique<int[]>() }
二者区别在于第一种方式初始化时()代表了指针指向区域的初始化值为多少
第二种则是初始化通过()来声明有几个成员。
它的好处目前也没能感知到,百度看了几个大致说法就是更安全更简单,至于不能使用定制删除器和不能完美传递一个initializer_list都是目前没感知的。得等以后深入用到了在挖了。
rest()
reset能够释放智能指针的内存空间,并将其置为nullptr;
1 | std::unique_ptr<int> intP{ new int{0} }; |
内存地址置空跟变成全0意思相同,就是说没有地址了,申请的内存也还给系统了。
get()
一开始使用智能指针的时候会感觉碍手碍脚,不像传统指针能通过*p = 直接改变值的过程
所以get方法可以让一个指针指向智能指针指向的内存区域。
1 | int *p; |
可以看到指针p也指向了智能指针指向的区域
然后进行修改:
1 | int *p; |
先初始化了智能指针的值为0,p在指向智能指针
然后通过*p=500也是成功修改了智能指针的值。
release()
release会返回unique_ptr的指针将其置为nullptr,但是release不会释放占用的内存空间。
1 | std::unique_ptr<int> intP{ new int{0} }; |
虽然release将智能指针的地址置为nullptr了,但是我们说过,原先的内存没有释放掉,而且release会返回原先智能指针的地址
1 | int *p; |
这样就可以看出没release之前intP的地址和release之后的结果。包括p接收了release返回的地址。
转移
智能指针具有唯一性是上述提到过的。所以智能指针不能够被复制,但是有转移的方法。
1 | std::unique_ptr<int> intP{ new int{0} }; |
看到intP被转移后地址被置为nullptr,intP2则获取了intP原先的地址。
结语
这玩意目前还不知道应用场景在哪,毕竟不太习惯。