首页 / C++ / C++智能指针初学小结
C++智能指针初学小结
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C++智能指针初学小结,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4903字,纯文字阅读大概需要8分钟。
内容图文
![C++智能指针初学小结](/upload/InfoBanner/zyjiaocheng/1255/d5633a2b97d44af1827d5064d17f501e.jpg)
本篇随笔仅作为个人学习《C++ Primer》智能指针一节后的部分小结,抄书严重,伴随个人理解。主要介绍shared_ptr、make_shared、weak_ptr的用法和联系。
C++通过一对运算符 new 和 delete 进行动态内存管理,new在动态内存中为对象分配空间并返回一个指向该对象的指针,delete接受一个动态对象的指针,销毁对象并释放与之相关的内存。然而这样的动态内存的使用很危险,因为无法确保始终能在合适的时间释放内存对象。如果忘记释放内存,可能造成内存泄露;如果在尚有指针引用内存的情况下释放内存,会产生非法访问内存的指针。
C++11中,新的标准库提供了两种智能指针(smart pointer)类型来更安全地管理对象。智能指针的使用和常规指针类似,只是它们多了自动释放所指向的对象的功能。两种指针的区别在于管理底层指针的方式:shared_ptr允许多个指针指向同一个对象,unique_ptr不支持。标准库还提供了weak_ptr这一弱指针,指向shared_ptr所管理的对象。三种类型都定义在头文件memory中。
shared_ptr的使用和vector很相似,在尖括号内说明所指向对象的类型:
shared_ptr<string> p1 // p1是shared_ptr,指向string类型 shared_ptr<list<int>> p2 // p2是shared_ptr,指向list的int
解引用一个智能指针就能获得它所指向的对象,在if语句中使用智能指针可以判断它指向的对象是否为空:
// 如果p1非空,检查p1是否指向一个空的string对象 if (p1 && p1->empty()) *p1 = "creat"; // 如果p1非空且指向一个空的string对象,解引用p1,为其赋新值creat
最安全的分配和使用shared_ptr的方法是调用名为make_shared这一标准库函数。此函数在动态内存中分配并初始化它,返回指向此对象的shared_ptr。该函数定义在memory中。
make_shared的定义和shared_ptr相似,必须制定要创建对象的类型,如:
// 指向一个值为1的int的shared_ptr shared_ptr<int> p3 = make_shared<int>)(1); // 指向一个值为“www”的string的shared_ptr shared_ptr<string> p4 = make_shared<string>(3, "w"); // 指向一个初始化的int,值为0 shared_ptr<int> p5 = make_shared<int>)();
也可以使用auto定义对象保存make_shared,可以省去书写shared_ptr的麻烦。
shared——ptr中有一个关联的指示器,称为引用计数。可以看做一个计数器,每当shared_ptr对象进行拷贝操作,如用一个shared_ptr对象初始化另一个shared_ptr对象、作为函数的实参、作为函数返回值时,引用计数都会递增(视为数值+1)。当赋予shared_ptr新值或者shared_ptr被销毁时,引用计数递减。当引用计数减为0,通过析构函数,shared_ptr自动销毁所管理的对象,释放内存。
需要注意的是,如果多个对象共享底层数据,当某一对象被销毁,不能单方面销毁底层数据,例如:
Blob<string> b1; { // 新作用域 Blob<string> b2 = { "x", "b", "b" }; b1 = b2; } // 当离开局部作用域,b2被销毁,然而b2中的元素xbb并不会被销毁 // b1指向最初由b2创建的元素,即“x”, "b", "b",b1依旧可以它们
weak_ptr是指向shared_ptr管理的对象的一种智能指针,然而它不控制所指向对象的生存期。将一个weak_ptr绑定在shared_ptr上,不会改变shared_ptr的引用计数,一旦最后一个shared_ptr的指向对象被摧销毁,对象就会被释放,有无weak_ptr并无卵影响。我的理解是,weak_ptr提供了指向shared_ptr底层数据的功能,控制了shared_ptr对底层数据的访问。
因为weak_ptr指向的对象可能不存在(shared_ptr指向的最后一个对象被销毁时),因而用它不能直接访问对象,必须调用lock函数检查其指向的对象是否存在。很容易写出一个选择语句进行控制:
auto bb = make_shared<string>(2, ‘b‘); weak_ptr<string> xbb(bb); if (shared_pr<int> np = xbb.lock()) { // np不为空条件成立 // 在if语句内,np和xbb共享对象 }
补充weak_ptr相关的函数,便于理解:
w.reset | 将w置为空 |
w.use_count() | 与w共享对象的个数 |
w.expired() | 若w.use_count()为0,返回true,否则返回false |
w.lock() | 若w.expired()为true,返回一个空shared_ptr,否则返回一个指向w的对象的shared_ptr |
加入《C++ Primer 5th》中的12.19题参照,题中和“智能指针和异常”并未在本篇随笔中介绍
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <memory> 5 #include <initializer_list> 6usingnamespace std; 7using std::string; 8using std::vector; 9class StrBlobPtr; 10class StrBlob { 11public: 12 friend class StrBlobPtr; // 友元13 StrBlobPtr begin(); // 声明StrBlob类中的begin()和end()14 StrBlobPtr end(); // 返回一个指向它自身的StrBlobPtr15public: 16 typedef vector<string>::size_type size_type; // 类型别名,size_type = vector<string>::size_type1718 StrBlob::StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {}; // 接受一个initializer_list参数的构造函数将其参数传 递给对应的vector构造函数,通过拷贝列表19 StrBlob::StrBlob() : data(make_shared<vector<string>>()) {}; // 构造函数,初始化data成员,指向动态分配的vector 中的值初始化vector元素20void push_back(conststring &t) { data->push_back(t); } 21string& StrBlob::front() { 22 check(0, "front on empty StrBlob"); 23return data->front(); 24 } 25string& StrBlob::back() { 26 check(0, "back on empty StrBlob"); 27return data->back(); 28 } 29void StrBlob::pop_back() { // 删除尾元素30 check(0, "pop_back empty StrBlob"); 31return data->pop_back(); 32 } 33string& front() const { return data->front(); }; 34string& back() const { return data->back(); }; 35private: 36 shared_ptr<vector<string>> data; 37void StrBlob::check(size_type i, conststring &msg) const { // 检查元素是否存在38if (i >= data->size()) // 若不存在39throw out_of_range(msg); // 抛出异常40 } 41}; 42class StrBlobPtr { 43public: 44 StrBlobPtr() : curr(0) {}; 45 StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) {}; 46string & deref() const { 47 auto p = check(curr, "dereference past end"); 48return (*p)[curr]; // check成功,返回一个p指针,指向make_shared指向的vector49 } // 解引用,make_shared获取vector,用下表运算符返回curr位置上的对象50 StrBlobPtr& incr() { 51 check(curr, "increment past end of StrBlobPtr"); 52 ++curr; 53return *this; 54 } 55booloperator!=(const StrBlobPtr& p) { return p.curr != curr; } 5657private: 58 weak_ptr<vector<string>> wptr; 59 size_t curr; 60 shared_ptr<vector<string>> check(size_t i, conststring& msg) const61 { 62 auto rent = wptr.lock(); 63if (!rent) 64throw runtime_error("unbound StrBlobPtr"); 65if (i >= rent->size()) 66throw out_of_range(msg); 67return rent; 68 } 69}; 70StrBlobPtr StrBlob::begin() 71{ 72return StrBlobPtr(*this); 73} 74StrBlobPtr StrBlob::end() 75{ 76return StrBlobPtr(*this, data->size()); 77 }
原文:http://www.cnblogs.com/xvbb/p/4990158.html
内容总结
以上是互联网集市为您收集整理的C++智能指针初学小结全部内容,希望文章能够帮你解决C++智能指针初学小结所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。