C++11 中推出了三种智能指针,unique_ptr、shared_ptr 和 weak_ptr,同时也将 auto_ptr 置为废弃 (deprecated)。
但是在实际的使用过程中,很多人都会有这样的问题:
在编程语言中,对堆对象的内存管理是一个麻烦又复杂的问题。一不小心就会带来问题(堆上数据通过指针来访问。)
C++里多个变量指向同一块内存导致重复释放。本文简单探讨一下关于对象所有权的问题
明白了对象所有权,我们才可以正确管理好对象生命周期和内存问题。
对象的所有权意味着当我们分配一个对象的时候,谁持有这个对象的所有权
既然智指针,能避免内存泄漏问题,
能代替all场景的原始指针吗?,
为什么发明三个 而不是一个,来一统天下。
答:不是的,如果使用不当会造成 core 或者 不执行析构函数。
在类的成员,或者函数参数传递。
如果 weak_ptr 指向某一 shared_ptr 指针拥有的堆内存, 则 weak_ptr 也指向该块存储空间(可以访问,但无所有权)
weak_ptr:
element_type * px; // contained pointer
boost::detail::weak_count pn; // reference counter
weak_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
if( tmp != pi_ )
{
if(tmp != 0) tmp->weak_add_ref();
if(pi_ != 0) pi_->weak_release();
pi_ = tmp;
}
return *this;
}
如果 weak_ptr 指向某一 shared_ptr 指针拥有的堆内存, 则 weak_ptr 也指向该块存储空间(可以访问,但无所有权)
#include <iostream>
#include <memory>
using namespace std;
int main()
{
std::shared_ptr<int> sp1(new int(10));
std::shared_ptr<int> sp2(sp1);
std::weak_ptr<int> wp(sp2);
//输出和 wp 同指向的 shared_ptr 类型指针的数量
cout << wp.use_count() << endl;
//释放 sp2
sp2.reset();
cout << wp.use_count() << endl;
//借助 lock() 函数,返回一个和 wp 同指向的 shared_ptr 类型指针,获取其存储的数据
cout << *(wp.lock()) << endl;
return 0;
}
程序执行结果为:2 1 10
element_type * px; // contained pointer
boost::detail::shared_count pn; // reference counter
敲黑板:shared_ptr 放到一个类中,这个类值传递,shared_ptr值义 ,不考虑内部的copy问题。但是但是双向链表成员 不能用shared_ptr表示
#include<iostream>
#include<memory>
using namespace std;
struct Node
{
int _value;
//shared_ptr<Node> _next;
//shared_ptr<Node> _prev;
weak_ptr<Node> _next;
weak_ptr<Node> _prev;
~Node()
{
cout << " ~Node() "<<_value << endl;
}
Node( int input)
{
_value = input;
}
};
int main()
{
shared_ptr<Node> sp1(new Node(1));
shared_ptr<Node> sp2(new Node(2));
sp1->_next = sp2; //为什么:shared_ptr 转变成 weak_ptr 不增加 shared_ptr引用计数呢?
sp2->_prev = sp1; //为什么:shared_ptr 转变成 weak_ptr 不增加 shared_ptr引用计数呢?
cout<<sp1.use_count()<<endl; //引用计数-->1 不是 2
cout << sp2.use_count() << endl; //引用计数-->1 不是 2
return 0;
}
//https://blog.csdn.net/qq_36430106/article/details/89441856
敲黑板:
对象的延迟销毁。陈硕在《Linux 多线程服务器端编程》中提到,当一个对象的析构非常耗时, 甚至影响到了关键线程的速度。可以使用 BlockingQueue<std::shared_ptr> 将对象转移到另外一个线程中释放, 从而解放关键线程。
敲黑板:
//用了unique_ptr为什么会core, 这是unique_ptrbug吗?
void TestAutoPtr5()
{
std::cout << "TestAutoPtr5 Test" << std::endl;
std::vector<std::unique_ptr<SimpleTest>> vc;
vc.push_back(std::unique_ptr<SimpleTest>(new SimpleTest(5)));
vc.push_back(std::unique_ptr<SimpleTest>(new SimpleTest(6)));
vc.push_back(std::unique_ptr<SimpleTest>(new SimpleTest(7)));
// 1-----
for (std::vector<std::unique_ptr<SimpleTest>>::iterator iter = vc.begin();
iter != vc.end(); iter++)
{
(*iter)->DoSomething();
}
// 2-----
vc.resize(5);
//可看出智能指针尽量不要指向vector容器类型,因为当vector扩容时,智能指针便不再生效,引起程序的崩溃或未定义的行为。
for (std::vector<std::unique_ptr<SimpleTest>>::iterator iter = vc.begin();
iter != vc.end(); iter++)
{
(*iter)->DoSomething();
}
}