动态内存 与 智能指针
参考https://www.cnblogs.com/lanxuezaipiao/p/4132096.html#top 与c++ primer第五版(p432)
1.动态内存与智能指针
- 智能指针包含在头文件<memory>中,shared_ptr、unique_ptr、weak_ptr。
- 智能指针与普通指针区别在于,它负责自动释放所指向的对象。
- shared_ptr 允许多个指针指向同一个对象,unique_ptr 则独占所指向的对象,二者管理底层指针的方式不同。
- 智能指针类似于vector,也是模板
程序使用动态内存的三个原因:
- 程序不知道自己需要使用多少个元素;例如容器类
- 程序不知道所需对象的准确类型; 15章涉及
- 程序需要在多个对象之间共享数据。
2.share_ptr
2.1 make_shared函数
此函数在动态内存中分配一个对象并初始化,返回指向该对象的shared_ptr。
//指向了一个值为42的int的shared_ptr shared_ptr<int> p3 = make_shared<int>42; //传递的参数必须与string的某个构造函数相匹配 shared_ptr<string>p4=make_shared<string>(10,'9');
2.2 shared_ptr的拷贝与赋值
每一个shared_ptr都关联一个计数器,称为引用计数。
一旦计数器为0,会自动释放所管理的对象,即shared_ptr的析构函数销毁对象,释放其内存。
auto r = make_shared<int>(42);
r = p; //给r赋值,递减r原来指向对象的引用计数
2.3 使用动态生存期的类
前面我们使用的类中,分配的资源与使用的对象的生存周期一致;如下:
vector<int> v1; { vector<int> v2={1,2}; v1=v2; } //v2和它的元素均被销毁; // v1中有三个元素,是v2 的拷贝
但某些类分配的资源与使用的对象的生存周期相互独立。
Blob<string> b1; {//新作用域 Blob<string> b2={"1","1"}; b1=b2; }//b2被销毁,但b2中的元素没有销毁
StrBlob是一个管理string的类,借助标准库容器vector,以及动态内存管理类shared_ptr,我们将vector保存在动态内存里,这样就能在多个对象之间共享内存。strBlob的data成员是一个指向vector<string>的shared_ptr,因此StrBlob的赋值不会拷贝vector的内容,而是多个StrBlob对象共享一个vector对象。
StrBlob.h
1 #include <vector> 2 #include <string> 3 #include <memory> 4 using namespace std; 5 class StrBlob 6 { 7 public: 8 typedef vector<string>::size_type size_type; 9 //构造函数 10 StrBlob(); 11 StrBlob(initializer_list<string> il); 12 //大小 13 size_type size() const {return data->size();} 14 bool empty() const {return data->empty();}; 15 //添加和删除元素 16 void push_back(const string& t) { data->push_back(t);}; 17 void pop_back(); 18 //元素访问 19 std::string& front(); 20 std::string& back(); 21 private: 22 std::shared_ptr<vector<string>> data; 23 //data[i]不合法时,抛出异常 24 void check(size_type i, const string &msg) const; 25 };
定义成员函数及使用:
1 #include<iostream> 2 #include "StrBlob.h" 3 #include <exception> 4 using namespace std; 5 //默认构造函数 6 StrBlob::StrBlob():data( make_shared<vector<string>>() ){} 7 //接受单一参数的构造函数 8 StrBlob::StrBlob(initializer_list<string> il): 9 data( make_shared<vector<string>>(il) ){} 10 //检查一个给定索引是否在范围内 11 void StrBlob::check(size_type i, const std::string &msg) const 12 { 13 if(i >= data->size()) 14 throw std::out_of_range(msg); 15 } 16 string& StrBlob::front() 17 { 18 //vector为空,会抛出异常 19 check(0, "front on empty StrBlob"); 20 return data->front(); 21 } 22 string& StrBlob::back() 23 { 24 check(0, "back on empty StrBlob"); 25 return data->back(); 26 } 27 28 void StrBlob::pop_back() 29 { 30 check(0, "pop_back on empty StrBlob"); 31 return data->pop_back(); 32 } 33 34 int main(){ 35 StrBlob b1; 36 StrBlob b2={"wang","dewd","dwerr"}; 37 b1=b2; 38 b2.push_back("about"); 39 cout<<b1.size()<<" "<<b1.front(); 40 return 0; 41 }