C++动态内存与智能指针(一)

概述:

在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对该对象初始化;delete,接受一个动态对象的指针,销毁该对象,并释放与之相关的内存。

动态内存很容易出问题,因为确保在正确时间释放内存是及其困难的。有时候忘记释放内存,就会产生内存泄露;有时候过早的释放内存,就会产生引用非法的内存指针。

新的标准提供了两种智能指针(smart pointer)类型管理动态对象。智能指针的行为类似常规指针,重要的区别是它负责自动的释放内存对象。shared_ptr允许多个指针指向同一个对象;unique_ptr则“独占”指向的对象。标准库还定义了一个week_ptr的伴随类,他是一种若引用,指向shared_ptr所管理的对象。

1.1 shared_ptr类

类似vector,智能指针也是模板。因此当创建一个智能指针时,必须提供额外的信息----指向可以指向的类型。与vector一样,我们在尖括号内给出类型,之后是所定义的这种智能指针的名字:

                        shared_ptr<string> p1;

                        shared_ptr<int> p2;

默认初始化的智能指针保存一个空指针。智能指针和普通指针类似,解引用一个智能指针返回它所指向的对象。如果一个条件判断中使用智能指针,效果就是检测它是否为空:

if(p1&&p1->empty()

{

   *p1="hi";

}

1.1表列出了shared_ptr和unique_ptr都支持的操作。1.2表只适用于shared_ptr。

表1.1 shared_ptr 和unique_ptr都支持的操作
shared_ptr<T> sp                 智能空指针,可以指向类型为T的对象
unique_ptr<T> up
p                                               将p用作于一个条件判断,若p指向一个对象,则为true
*p                                              解引用p,获得他指向的对象
p->mem                                   等价于(*p).mem
p.get()                                       返回p中保存的指针。要小心是哟功能,如智能指针释放了其对象,返回的指针指向的对象也消失了
swap(p,q)                                 交换p和q中的指针


表1.2:shared_ptr 独有的操作
make_shared<T>(args)              返回一个shared_ptr对象,指向一个动态分配的类型为T的对象。使用args初始化此对象
shred_ptr<T> p(q)                        p是shared_ptr q的拷贝;此操作会递增q中的计数器。q中的指针必须能转换为T*
p=q;                                                  p和q都是shared_ptr,所保存的智能指针必须能相互互换。此操作会递减p的引用计数,递增q的引用计数,若p的引用计数为0,则将
                                                           其管理的内存释放。
p.unique()                                     若p.use_count()为1,返回true,否则返回false
p.use_count()                              返回与p共享对象的智能指针的数量。主要用于调试

make_shared  函数

最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数。此函数在动态内存中分配一个对象并初始化它,返回此对象的shared_ptr。与智能指针一样,也定义在头文件memory中。

shared_ptr<int> p3=make_shared<int>(3);

shared_ptr<string> p4=make_shared<string>("this is ");

通常用auto定义一个对象来保存make_shared的结果

auto p6=make_shared<vector<string>>();

shared_ptr 的拷贝和赋值

当进行拷贝或赋值操作时,每个shared_ptr都会记录有多少个shared_ptr指向相同的对象:

auto p=make_shared<int>(42);//p指向的对象只有p一个引用者

auto q(p);//p和q指向相同的对象,此对象有两个引用者

无论何时我们拷贝一个shared_ptr ,计数器都会递增。例如,当用一个shared_ptr初始化另一个shared_ptr,或将它作为一个参数传递给一个函数时,一节作为函数的返回值时,它所关联的计数器都会递增。

shared_ptr 自动销毁管理的对象

shared_ptr 的析构函数会递减它所指向的对象的引用计数。如果计数变为0,shared_ptr的析构函数就会销毁对象,并释放它所暂用的内存。


shared_ptr 还会自动释放想关联的内存

如果我们有一个函数,它返回一个shared_ptr,带一个Foo类型的分配对象,对象是通过一个类型为T的参数进行初始化的:

//factory返回一个shared_ptr,指向一个动态分配的对象

shard_ptr<Foo> factory(T args)

{

//shared_ptr负责释放内存

   return make_shared<Foo>(args);

}

由于factory返回一个shared_ptr,所以我们可以确保它分配的对象在恰当的时刻被释放。

void use_factory(T arg)

{

shared_ptr<Foo> p=factory(arg);


}//p离开作用域时,它指向的内存会被自动释放

如果还有其他的shared_ptr指向这块内存,他就不会被释放。例如返回值。


使用了动态生存期的资源类

1 程序不知道自己需要使用多少对象

2 程序不知道所需对象的准确类型

3 程序需要在多个对象之间共享数据


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值