C++11中的智能指针

C++ 智能指针shared-ptr,unique_ptr和weak-ptr

C++11中的智能指针

C++11中有四种只能指针,auto_ptrshared-ptrunique_ptrweak-ptr。其中auto_ptr有和多不足之处,在C++11中已经建议废弃使用。

shared_ptr

智能指针也是模板。所以创建智能指针时要提供其指向的指针类型:

shared_ptr<string>p1; //指向string

shared_ptr<list<int>>p2 //指向intlist,在C++11<list<int>>中的>>再也不用空格了


在给shared_ptr分配内存时建议使用make_shared函数,这样最安全。它与智能指针的头文件相同都位于memory头文件中。


//指向一个值为42intshared_ptr

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

//指向一个值为”9999999999”string

shared_ptr<string>p4=make_shared<string>(10,' 9');

//p5指向一个值初始化的int,即值为0

shared_ptr<int>p5=make_shared<int>();


make_shared函数中的参数可以是其指向类型中拥有的构造函数的参数一样。

当对shared_ptr进行拷贝和赋值操作每个shared_ptr都会记录它所指向对象的个数,一般称之为引用计数。当进行拷贝操作时他们所指向的对象的引用计数都会增加,一旦一个shared_ptr的引用计数变为0,它就会自动释放自己所管理的对象。

autor=make_shared<int>(42);

r=q;//r原来对象的引用计数会减1,而其新指向的对象的引用计数会加1.

shared_ptr的引用计数变为0,它就会调用所指向类型的析构函数来释放内存,但注意是调用delete来释放的,当其指向数组时要手动指定释放函数。

智能指针在异常发生时也能释放其拥有的内存。

void f()

{

int*p=new int(42);

//在这段代码之间发生了一异常

deletep;

}

如果在newdelete之间发生一场且异常没有在f中捕获,则内存永远不会释放了。

假设为们正在使用一个CC++的网络库,有如下代码:

struct destination;

struct connection;

connection connect(destination *);

void disconnection(connection);

void f(destination &d)

{

connection c=connection(&d);

//若我们在f退出前忘记使用disconnection,就无法关闭c

}

可以采用一下方法来解决这种问题

默认shared_ptr是使用delete来释放其所只想对象的内存的,我们可以自定义一个函数来代替delete,这个删除器(deleter)函数必须能够完成对shared_ptr中保存的指针进行释放操作。在上述例子中删除其必须接受单个类型为connection*的参数:

voidedn_connection(connection *p){disconnection(*p);}

当我们创建一个shared_ptr可以传递一个指向删除器的参数

voidf(destination &d)

{

connectionc=connection(&d);

shared_ptr<connection>p(&c,end_connection);

//若我们在f退出时(即使是由于异常而退出),connection会被正确关闭

}

使用智能指针时应注意一下5点:

1.不使用内置指针初始化(或reset)多个只能指针。

2.deleteget()返回的指针。

3.不使用get()初始化或reset另一个智能指针

4.如果使用get()返回指针,记住最后一个对应的指针销毁后,你的指针就便为无效了。

5.如果你使用智能指针管理的资源不是new分配的内存,记住传递给它一个删除器

unique_ptr

一个unique_ptr“拥有”它所指向的对象,shared_ptr不同,某个时刻一个只能有一个unique_ptr指向一个给定的对象,unique_ptr被销毁时,其所指向的对象也被销毁了。

由于一个unique_ptr拥有它指向的对象,所以unique_ptr不支持普通的拷贝或赋值操作:

unique_ptr<string>p1(new string(“steven”));

unique_ptr<string>p2(p1); //错误,不支持拷贝操作

unique_ptr<string>p3;

p3=p2; //错误,不支持赋值操作

我们可有通过releasereset方法将指针的所有权从一个(const)unique_ptr转移给另一个unique_ptr

unique_ptr<string>p2(p1.release()); //p1放弃所有权,转交给p2

unique_ptr<string>p3(new string(“Trex”));

p2.reset(p3.release());

注意release()并不会释放内存只会转交拥有权,reset()可以释放内存。


不能拷贝unique_ptr的规则有一个例外,我们可以拷贝或复制一个将要被销毁的unique_ptr。最常见的就是从函数返回一个unique_ptr:

unique_ptr<int>clone(int p)

{

//正确

return unique_ptr<int> (new int(p));

}

还可以返回一个局部对象的拷贝:

unique_ptr<int>clone(int p)

{

//正确

unique_ptr<int>ret(new int(p));

return ret;

}

这种机制的实现是使用的是C++11的新语法std::move(),它可以“窃取”资源而不是拷贝资源。具体可以参考std::move()相关知识

unique_ptr中的删除器

类似shared_ptrunique_ptr默认情况下用delete释放它指向的对象。在构建时必须提供删除器的类型。

unique_ptr<objT, delT>p (new objT,fcn);

unique_ptr代替上面连接程序

void f(destination &d)

{

connection c=connection(&d);

unique_ptr<connection,decltype(end_connection)*>p(&c,end_connection);

//若我们在f退出时(即使是由于异常而退出),connection会被正确关闭

}

weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针,它指向一个shared_ptr管理的对象。将一个weak_ptr绑定到shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向对象,对象还是会被释放。

当我们创建一个weak_ptr时,要用一个shared_ptr来初始化它:

auto p=make_shared_ptr<int>(42);

weak_ptr<int>wp(p); //wp弱共享pp的引用计数未改变

由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock().此函数检查weak_ptr指向的对象是否存在。如果存在lock则返回一个指向共享对象的shared_ptr,同时该对象的引用计数会增加

if(shared_ptr<int> np= wp.lock())

{

}

智能指针和动态数组

标准库提供了一个可以管理new分配数组的unique_ptr版本,为了用一个unique_ptr管理动态数组,我们必须在对象类型后面跟一对方括号。

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

up.realese();//自动用delete[]销毁其指针。

unique_ptr指向数组时我们不能使用点和箭头运算符,而是用下标来访问数组中的元素:

for(size_ti=0;i I != 10; ++i)

up[i]=i;


unique_ptr<T[]>u //u指向一个类型为T的动态分配的数组

unique_ptr<T[]>u (p) //u指向内置指针p所指向的动态分配的数组。P必须能转换为类型T

u[i] //返回位置i的元素



unique_ptr不同,shared_ptr不直接支持管理共带数组,如果希望使用shared_ptr管理一个数组必须提供一个自定义的删除器:

share_ptr<int[]>sp(new int[10] , [](int *p){delete[] p;}); //这里使用了lambda表达式

sp.reset();

for(size_ti=0;i I != 10; ++i)

*(sp.get()+i)=i;//由于shared_ptr不直接支持动态数组所以我们不能用下标直接访问元素。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++11引入了智能指针,它们是一种用于管理动态分配的内存的工具。智能指针可以自动处理内存的释放,避免了手动释放内存的麻烦和可能的内存泄漏。C++11提供了三种类型的智能指针:unique_ptr、shared_ptr和weak_ptr。 1. unique_ptr:unique_ptr是一种独占所有权的智能指针,它确保只有一个指针可以访问给定的资源。当unique_ptr超出作用域或被重新赋值时,它会自动释放所管理的资源。以下是一个unique_ptr的示例: ```cpp #include <memory> int main() { std::unique_ptr<int> ptr(new int(10)); // 使用ptr指向的资源 std::cout << *ptr << std::endl; // unique_ptr会在超出作用域时自动释放资源 return 0; } ``` 2. shared_ptr:shared_ptr是一种共享所有权的智能指针,它可以被多个指针同时访问同一个资源。shared_ptr使用引用计数来跟踪资源的使用情况,当最后一个shared_ptr超出作用域时,资源会被释放。以下是一个shared_ptr的示例: ```cpp #include <memory> int main() { std::shared_ptr<int> ptr1(new int(10)); std::shared_ptr<int> ptr2 = ptr1; // 使用ptr1或ptr2指向的资源 std::cout << *ptr1 << std::endl; std::cout << *ptr2 << std::endl; // shared_ptr会在最后一个引用超出作用域时释放资源 return 0; } ``` 3. weak_ptr:weak_ptr是一种弱引用的智能指针,它可以指向shared_ptr所管理的资源,但不会增加引用计数。weak_ptr主要用于解决shared_ptr的循环引用问题。以下是一个weak_ptr的示例: ```cpp #include <memory> int main() { std::shared_ptr<int> ptr1(new int(10)); std::weak_ptr<int> ptr2 = ptr1; // 使用ptr1或ptr2指向的资源 std::cout << *ptr1 << std::endl; if (auto sharedPtr = ptr2.lock()) { // 使用ptr2指向的资源 std::cout << *sharedPtr << std::endl; } // weak_ptr不会影响资源的生命周期 return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值