C/C++面试:什么是智能指针?智能指针有什么作用?分为哪几种?各自有什么样的特点?

您所在的位置:网站首页 人工智能词条有什么用途 C/C++面试:什么是智能指针?智能指针有什么作用?分为哪几种?各自有什么样的特点?

C/C++面试:什么是智能指针?智能指针有什么作用?分为哪几种?各自有什么样的特点?

2024-07-10 06:09| 来源: 网络整理| 查看: 265

说下你对智能指针的理解

因为C++使用内存的时候很容易出现野指针、悬空指针、内存泄露的问题。所以C++11引入了智能指针来管理内存。有四种:

auto_ptr:已经不用了unique_ptr:独占式指针,同一时刻只能有一个指针指向同一个对象shared_ptr:共享式指针,同一时刻可以有多个指针指向同一个对象weak_ptr:用来解决shared_ptr相互引用导致的死锁问题

重要提醒:回答这样就可以了,回到一大段一大段的!!!

unique_ptr能否被另一个unique_ptr拷贝呢? 不能,因为它把它的拷贝构造函数private了。但是它提供了一个移动构造函数,所以可以通过std::move将指针指向的对象交给另一个unique_ptr,转交之后自己就失去了这个指针对象的所有权,除非被显示交回 unique_ptr和shared_ptr的区别

(1)

unique_ptr代表的是专属所有权,不支持复制和赋值。但是可以移动shared_ptr 代表的是共享所有权,shared_ptr 是支持复制的和赋值以及移动的

(2)资源消耗上

unique_ptr 在默认情况下和裸指针的大小是一样的。 所以 内存上没有任何的额外消耗,性能是最优的,我们大多数场景下用到的应该都是 unique_ptr。shared_ptr 的内存占用是裸指针的两倍。因为除了要管理一个裸指针外,还要维护一个引用计数。因此相比于 unique_ptr, shared_ptr 的内存占用更高。在使用 shared_ptr 之前应该考虑,是否真的需要使用 shared_ptr, 而非 unique_ptr。 unique_ptr = unique_ptr和shared_ptr=shared_ptr这两个操作有什么后果呢?

先来说下unique_ptr :

这个操作是不允许的,因为unique_ptr它的原理是将拷贝构造和拷贝赋值私有化,但是它提供了移动构造和移动赋值。所以如果你想要使用=赋值,必须先把右边的用std::move包裹一下,这样右边的unique_ptr就会失去所有权,左边的unique_ptr就会得到对应对象的所有权

至于shared_ptr:

对于左边的指针,它会将自己的引用计数减一,然后检测一下是不是减到了0,如果是,那么delete所管理的对象然后将右边的引用计数和管理对象赋值给左边,此时两边指向同一个对象,共享同一个引用计数,然后引用计数++ shared_ptr的移动赋值时发生了什么事情 首先它会检查本指针和参数指针是不是同一个对象,如果是,直接返回然后,先把本指针的引用变量–,如果发现减到了0,就把参数指针和参数引用变量析构掉并置NULL最后,本指针和参数指针指向同一个对象以及引用计数,然后引用计数自增1 shared_ptr什么时候会被释放掉,就是什么时候引用次数为0? 在一个shared_ptr析构时,或者被赋值时,强引用计数会减1。减到0就delete资源 shared_ptr你是怎么实现的

shared_ptr 内部是利用引用计数来实现内存的自动管理,每当复制一个 shared_ptr,引用计数会 + 1。当一个 shared_ptr 离开作用域时,引用计数会 - 1。当引用计数为 0 的时候,则 delete 内存。

关键在于多个对象持有同一个引用对象,第一次创建指针的时候可以new一个int,然后大家都有一个int指针就可以共用了

shared_ptr应该要有三个成员:

裸指针:指向所要管理的对象强引用计数:就是一个int指针,记录了有多少个shared_ptr指向裸指针弱引用计数:也是一个int指针,记录了有多少个weak_ptr指向裸指针 shared_ptr是不是线程安全 不是引用计数的增减是原子操作没问题,但是shared_pytr的读写本身不只包括引用计数操作,还包括资源所有权的操作,这两个操作合起来不是原子的如果要求线程安全必须加锁 sharedPtr在64位操作系统下大小有多大 两个指针,64字节 shared_ptr和weak_ptr之间是什么关系? weak_ptr是用来辅助shared_ptr的,每一个weak_ptr它指向weak_ptr而不是实际的操作函数 为什么推荐用makeshared创建指针

优点是:

它分配的时候,只分配一次,而shared_ptr的构造函数需要分配两次。效率更高更安全 缺点是:如果有weak_ptr不推荐使用,否则会出现知道最后一个weak_ptr被释放了才真正去释放管理的对象 为什么要用 shared_from_this?

我们往往会需要在类内部使用自身的 shared_ptr,例如:

class Widget { public: void do_something(A& a) { a.widget = 该对象的 shared_ptr; } }

我们需要把当前 shared_ptr 对象同时交由对象 a 进行管理。意味着,当前对象的生命周期的结束不能早于对象 a。因为对象 a 在析构之前还是有可能会使用到 a.widget。

如果我们直接 a.widget = this;, 那肯定不行, 因为这样并没有增加当前 shared_ptr 的引用计数。shared_ptr 还是有可能早于对象 a 释放。

如果我们使用 a.widget = std::make_shared(this);,肯定也不行,因为这个新创建的 shared_ptr,跟当前对象的 shared_ptr 毫无关系。当前对象的 shared_ptr 生命周期结束后,依然会释放掉当前内存,那么之后 a.widget 依然是不合法的。

对于这种,需要在对象内部获取该对象自身的 shared_ptr, 那么该类必须继承 std::enable_shared_from_this。代码如下:

class Widget : public std::enable_shared_from_this { public: void do_something(A& a) { a.widget = shared_from_this(); } }

这样才是合法的做法。

weak_ptr的原理? shared_ptr中有一个成员时,弱引用计数。往weak_ptr被赋值时,弱引用计数自增1 weak_ptr的使用场景 用来解决悬空指针问题。通过std::shared_ptr管理数据并将std::weak_ptr提供给数据用户,用户可以通过expired()或者lock()来检测数据的有效性打破shared_ptr相互引用导致死锁的问题。方法:将任意一个改为weak_ptr有时候我们需要“如果对象还活着,就调用它的成员函数,否则忽略之”的语意缓存对象 关于shared_ptr相互引用具体讲一下

weak_ptr 是为了解决 shared_ptr 双向引用的问题。即:

class B; struct A{ shared_ptr b; }; struct B{ shared_ptr a; }; auto pa = make_shared(); auto pb = make_shared(); pa->b = pb; pb->a = pa;

pa 和 pb 存在着循环引用,根据 shared_ptr 引用计数的原理,pa 和 pb 都无法被正常的释放。 对于这种情况, 我们可以使用 weak_ptr:

class B; struct A{ shared_ptr b; }; struct B{ weak_ptr a; }; auto pa = make_shared(); auto pb = make_shared(); pa->b = pb; pb->a = pa;

weak_ptr 不会增加引用计数,因此可以打破 shared_ptr 的循环引用。 通常做法是 parent 类持有 child 的 shared_ptr, child 持有指向 parent 的 weak_ptr。这样也更符合语义。

weak_ptr如何检测指针是否被销毁

expired():

判断强引用计数是否为0如果返回true,那么被观测的对象(也就是shared_ptr管理的资源)已经不存在了 如何将weak_ptr转换为shared_ptr

用lock():

如果expired()为true,返回一个空shared_ptr,否则返回非空shared_ptr。 lambda有哪几种捕获方式

在这里插入图片描述

用lambda捕获uniquePtr应该怎么做

引用捕获,因为uniquePtr没有拷贝构造

我们在lambda表达式中使用的是按值传递; 按值传递就会产生副本,就会产生一个unique_ptr的copy; 但是我们知道的,这显然是错误。解决方法很简单,就是按引用传递替代按指针传递: auto str = std::make_unique("my string"); auto lambda = [capturedStr = std::move(str)]{ std::cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3