c++中的智能指针
由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete,用智能指针便可以有效缓解这类问题。
对于编译器来说,智能指针实际上是一个栈对象,并非指针类型,在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。所有智能指针都重载了“operator->”操作符,直接返回对象的引用,用以操作对象。访问智能指针原来的方法则使用“.”操作符。
访问智能指针包含的裸指针则可以用 get() 函数
智能指针包含了 reset() 方法,如果不传递参数(或者传递 NULL),则智能指针会释放当前管理的内存。如果传递一个对象,则智能指针会释放当前对象,来管理新传入的对象。
- 编写测试类来辅助分析
class Simple { |
std::auto_ptr
包含头文件 #include<memory>
便可以使用std::auto_ptr
能够方便的管理单个堆内存对象
用法一:std::auto_ptr<MyClass>m_example(new MyClass());
用法二:std::auto_ptr<MyClass>m_example;
m_example.reset(new MyClass());
用法三(指针的赋值操作):std::auto_ptr<MyClass>m_example1(new MyClass());
std::auto_ptr<MyClass>m_example2(new MyClass());
m_example2=m_example1;
使用示例
void TestAutoPtr() { |
- 执行结果为:
Simple: 1
PrintSomething:
PrintSomething: Addition
PrintSomething: Addition other
~Simple: 1
不能使用 = 操作符
void TestAutoPtr2() { |
my_memory2 = my_memory
这行代码,my_memory2 完全夺取了 my_memory 的内存管理所有权,导致 my_memory 悬空,最后使用时导致崩溃。
release() 函数问题
void TestAutoPtr3() { |
调用 release() 函数释放内存,不会释放对象,仅仅归还所有权,要自己 delete 或使用 reset()函数销毁对象
//代码修正 |
- 注意事项
使用 std::auto_ptr 时,绝对不能使用“operator=”操作符,这会夺取内存管理所有权
std::auto_ptr 的 release() 函数不会释放对象,仅仅归还所有权。
std::auto_ptr 最好不要当成参数传递(读者可以自行写代码确定为什么不能)。
std::auto_ptr 的“operator=”问题,有其管理的对象不能放入 std::vector 等容器中。
C++11 中,std::auto_ptr 已经被弃用
自 C++11 起,C++标准提供两大类型的智能指针:shared_ptr 和 unique_ptr
std::shared_ptr
shared_ptr 实现共享式拥有(shared ownership)概念。多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用(reference)被销毁”时候释放。为了在结构复杂的情境中执行上述工作,标准库提供了 weak_ptr、bad_weak_ptr 和 enable_shared_from_this 等辅助类。
shared_ptr 本身提供默认内存释放器(default deleter),调用的是 delete,也可以自定义释放器
默认内存释放器并不能释放数组内存空间,要我们自己提供内存释放器
成员函数
use_count 返回引用计数的个数
unique 返回是否是独占所有权( use_count 为 1)
swap 交换两个 shared_ptr 对象(即交换所拥有的对象)
reset 放弃内部对象的所有权或拥有对象的变更, 会引起原有对象的引用计数的减少
get 返回内部对象(指针)示例
std::shared_ptr<int> sp0(new int(2)); |
- 注意事项
shared_ptr 会因循环引用造成无法释放资源
与 weak_ptr 一起工作时, weak_ptr 在使用前需要检查合法性
shared_ptr 不支持数组, 如果使用数组, 需要自定义删除器
std::weak_ptr
weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。
weak_ptr 没有重载*和->但可以使用 lock 获得一个可用的 shared_ptr 对象. 注意, weak_ptr 在使用前需要检查合法性。
weak_ptr 支持拷贝或赋值, 但不会影响对应的 shared_ptr 内部对象的计数。
成员函数
expired 用于检测所管理的对象是否已经释放, 如果已经释放, 返回 true; 否则返回 false
lock 用于获取所管理的对象的强引用(shared_ptr). 如果 expired 为 true, 返回一个空的 shared_ptr; 否则返回一个 shared_ptr, 其内部对象指向与 weak_ptr 相同。
use_count 返回与 shared_ptr 共享的对象的引用计数.
reset 将 weak_ptr 置空.使用 weak_ptr 解决 shared_ptr 因循环不能释放资源的问题
使用 shared_ptr 时, shared_ptr 为强引用, 如果存在循环引用, 将导致内存泄露. 而 weak_ptr 为弱引用, 可以避免此问题
class CA |
std::unique_ptr
unique_ptr 实现独占式拥有(exclusive ownership)或严格拥有(strict ownership)概念,保证同一时间内只有一个智能指针可以指向该对象。它对于避免资源泄露(resourece leak)——例如“以 new 创建对象后因为发生异常而忘记调用 delete”——特别有用。
unique_ptr 不支持拷贝和赋值,但是可以调用 release 或 reset 将指针的所有权从一个(非 const) unique_ptr 转移到另一个std::unique_ptr<A> up1(new A(5));
std::unique_ptr<A> up2(up1);
// 错误, unique_ptr 不支持拷贝std::unique_ptr<A> up2 = up1;
// 错误, unique_ptr 不支持赋值std::unique_ptr<int> up2(up1.release());
// 正确
unique_ptr 不支持拷贝, 但是可以从函数中返回, 甚至返回局部对象
std::unique_ptr<Ty> Clone(const Ty& obj) |
unique_ptr 支持管理数组
成员函数
get 获得内部对象的指针
release 放弃内部对象的所有权,将内部指针置为空, 返回所内部对象的指针, 此指针需要手动释放
reset 销毁内部对象并接受新的对象的所有权(如果使用缺省参数的话,也就是没有任何对象的所有权, 此时仅将内部对象释放, 并置为空)
swap 交换两个 shared_ptr 对象(即交换所拥有的对象)
std::move(name) 所有权转移(通过移动语义), 所有权转移后,变成“空指针”防内存泄漏代码改进
int main() |
int main() |
int main() |
//使用 unique_ptr |
boost::scoped_ptr
boost::shared_ptr
boost::scoped_array
boost::shared_array
boost::weak_ptr
boost:: intrusive_ptr
参考资料:
https://blog.csdn.net/xt_xiaotian/article/details/5714477
https://www.cnblogs.com/xiehongfeng100/p/4645555.html
https://www.cnblogs.com/diysoul/p/5930361.html
https://www.cnblogs.com/diysoul/p/5930372.html
https://www.cnblogs.com/diysoul/p/5930388.html
- 本文链接:https://hyqskevin.github.io/2019/04/05/ptr/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!