浅谈C++智能指针
??语言上因为没有内存回收机制,所以需要使用者手动释放内存。但是,有时候我们可能会忘了将某个指针指向的内存释放掉,于是就造成了内存泄漏。为了改善或解决这个问题,C++11引入了智能指针对象,通过智能指针对象来管理这个要释放的内存。 ??智能指针主要通过引用计数机制来管理这个内存指针,引用计数为0的时候即内存不再被使用了,智能指针会帮我们释放掉这个内存。C++11引入的智能指针一共有下列几类:
- shared_ptr 共享指针,共享管理内存指针,引用计数为0时释放内存。
- weak_ptr 弱指针,主要为解决shared_ptr循环引用的问题而引入的。
- unique_ptr 唯一指针,无法拷贝复制,但可以被转移,释放。
相关的衍生模板类:
- std::enable_shared_from_this 提供shared_from_this()函数,可以增加对象自身的引用计数,前提是自身对象被shared_ptr管理。
??接下来,我将简单介绍一下智能指针的使用,并以源码来展示。
#include <iostream>
#include <memory>
#include <functional>
std::function<void()> task = nullptr;
//主要考虑有在成员函数里增加自身引用延迟声明周期时,
//才考虑继承enable_shared_from_this
class Demo : public std::enable_shared_from_this<Demo> {
public:
Demo() {
std::cout << "Demo()" << std::endl;
}
~Demo() {
std::cout << "~Demo()" << std::endl;
}
void testEnableSharedFromThis() {
std::cout << "i am testEnableSharedFromThis()" << std::endl;
task = std::bind(&Demo::testAsyncCallBack, shared_from_this());
a_ = 10;
}
void testAsyncCallBack() {
std::cout << "i am testAsyncCallBack() a_ " << a_ << std::endl;
}
private:
int a_;
};
int main(int argc, char* argv[]) {
//一般用法
{
std::shared_ptr<Demo> t1(new Demo());
}
//二般用法,比一般用法效率
{
std::shared_ptr<Demo> t2(std::make_shared<Demo>());
}
{
//t3 一个强引用
std::shared_ptr<Demo> t3(std::make_shared<Demo>());
//t3 一个强引用 1一个引用
std::weak_ptr<Demo> t4 = t3;
std::cout << "t3 强引用 " << t3.use_count() << std::endl;
//弱指针常用来处理循环引用的问题
//检查t4 弱指针是否过期(是否有效)
if (!t4.expired()) {
//尝试提升弱指针为共享指针
std::shared_ptr<Demo> t5 = t4.lock();
if (t5 == nullptr) {
std::cout << "weak_ptr to shared_ptr failed" << std::endl;
} else {
std::cout << "t3 强引用 " << t3.use_count() << std::endl;
}
} else {
std::cout << "t4 weak_ptr is expired" << std::endl;
}
}
{
//唯一指针,不能拷贝,不能赋值,但是可以转移所有权,通过std::move或者release成员函数
std::unique_ptr<Demo> t6(std::make_unique<Demo>());
std::unique_ptr<Demo> t7(std::move(t6));
if (t6 == nullptr) {
std::cout << "t6 is nullptr" << std::endl;
} else {
std::cout << "t6 is not nullptr" << std::endl;
}
std::unique_ptr<Demo> t8(t7.release());
if (t7 == nullptr) {
std::cout << "t7 is nullptr" << std::endl;
} else {
std::cout << "t7 is not nullptr" << std::endl;
}
if (t8 != nullptr) {
std::cout << "t8 != nullptr" << std::endl;
}
}
{
std::cout << "Test t9 begin" << std::endl;
//动态分配一个Demo对象,由t9管理
std::shared_ptr<Demo> t9(std::make_shared<Demo>());
t9->testEnableSharedFromThis();
//释放t9对象,但是上面分配的对象还存在,task有一个智能指针。
t9.reset();
}
{
std::cout << "I am task2 begin" << std::endl;
//交换task对象,在离开这个作用域后,task2对象被释放,前面的t9分配的内存也被释放
std::function<void()> task2;
task2.swap(task);
std::cout << "I am task2 end" << std::endl;
}
std::cout << "Test t9 finish, t9 has been freed ";
return 0;
}
??demo程序执行结果如下:
结尾
??好的,关于C++智能指针的介绍到这里就结束了。如果行文有不正之处,欢迎留言或私信指正。当然,如果你有更好的想法或意见,也可以留言或者私信。如果觉得还可以,点赞或关注下,码字不易,谢谢。
|