第12章 动态内存

第12章 动态内存

12.1 动态内存和智能指针

在C++中,动态内存的管理是通过运算符new和delete完成的。

智能指针类似常规指针,重要的区别是它负责自动释放所指向的对象。

智能指针类型
shared_ptr允许指针指向同一个对象
unique_ptr“独占”所指向的对象
weak_ptr弱引用,指向shared_ptr所管理的对象

12.1.1 shared_ptr类

12.1.2 直接管理内存

new和delete运算符

12.1.3 shared_ptr和new综合使用

share_ptr<double>p1;
share_ptr<int> p2(new int(42));//p2指向一个值为42的int

接受指针参数的智能指针构造函数是explicit的,因此,不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式来初始化一个智能指针:

shared_ptr<int> p1=new int(1024);//错误:必须使用直接初始化形式 int*创建shared_ptr(错误)
shared_ptr<int> p2(new int(1024));//正确:使用了直接初始化形式

12.1.4 智能指针和异常

在程序块正常处理或发生了异常,局部对象都会被销毁。若程序块中使用了智能指针,智能指针类可以确保内存被释放;若程序块中使用内置指针管理内存,并且在new之后delete之前发生了异常,则内存不会被正常释放。

12.1.5 unique_ptr

unique_ptr某个时刻只能指向一个对象,当它被销毁时,它所指向的对象也被销毁。不支持拷贝和赋值操作。

unique_ptr<int>p2(new int(42));
unique_ptr<string> p1(new string("Strgosaurus"));
unique_ptr<stirng>p2(p1);//错误:不支持拷贝
unique_ptr<string>p3;
p3=p2;//错误:unique_ptr不支持赋值

//可以调用release或reset将指针的所有权由一个(非const)unique_ptr转移给另一个unique

//将所有权从p1转移给p2
unique_ptr<string> p2(p1.release());//realease将p1置空
unique_ptr<string> p3(new string("Trex"));
//将所有权从p3转移到p2
p2.reset(p3.release());//reset释放了p2原来指向的内存

12.1.6 weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象,它不会改变shared_ptr的引用计数。

创建一个weak_ptr时,需要使用shared_ptr来初始化它:

auto p=make_shared<int>(42);
weak_ptr<int> wp(p);//wp弱共享p
检查指针类

定义StrBlob类的一个伴随指针类StrBlobPtr,该类保存一个weak_ptr,指向StrBlob的data成员。通过使用weak_ptr,不会影响一个给定的StrBlob所指向的vector的生存期。但是,可以阻止用户访问一个不再存在的vector的企图。

//对于访问一个不存在元素的尝试,StrBlobPtr抛出一个异常 .h
class StrBlobPtr{
public:
    StrBlobPtr():curr(0){}
    StrBlobPtr(StrBlob &a,size_t sz=0):wptr(a.data),curr(sz){}
    string& deref() const;
    StrBlobPtr& incr();//前缀递增


private:
    //若检查成功,check返回一个指向vector的shared_ptr
    shared_ptr<vector<string>> check(size_t,const string&) const;
    weak_ptr<vector<string>> wptr;
    size_t curr;//在数组中的位置
};

//.cpp
shared_ptr<vector<string>> StrBlobPtr::check(size_t i,const string &msg) const{
    auto ret=wptr.lock();//vector还存在吗
    if(!ret){
        throw runtime_error("unbound StrBlobPtr");
    }
    if(i>=ret->size()){
        throw out_of_range(msg);
    }
    return ret;//否则,返回指向vector的shared_ptr
}

12.2 动态数组

标准库中包含一个名为allocator的类,允许我们将分配和初始化分离。

分配动态数组的类必须定义自己版本的操作,在拷贝、复制以及销毁对象时管理所关联的内存。

12.2.1 new和数组

T *p=new T[];

返回T类型的指针,指向动态数组的首位。不用范围for语句来处理动态数组中的元素。

释放动态数组
delete [] p;//逆序销毁
智能指针和动态数组

unique_ptr可以管理new分配的数组

unique_ptr<int[]> up(new int[10]);

shared_ptr不直接支持的管理动态数组.若希望使用它管理动态数组,必须提供自己定义的删除器。

shared_ptr<int>sp(new int[10],[](int *p){delete[] p});

12.2.2 allocator类

new在灵活性上存在局限性,它将内存分配和对象构造组合在一起。当分配一大块内存时,我们通常在内存上按计划分配,只有需要对象时才真正执行对象创建操作。

allocator类

allocator类定义在memory头文件中,帮助我们将内存分配和对象构造分离开来。

allocator<string> alloc;//可以分配string的allocator对象
auto const p=alloc.allocate(n);//分配n个未初始化的string
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值