某日二师兄参加XXX科技公司的C++工程师开发岗位第19面:

面试官:什么是智能指针?

二师兄:智能指针是C++11引入的类模板,用于管理资源,行为类似于指针,但不需要手动申请、释放资源,所以称为智能指针。

面试官:C++11引入了哪些智能指针?

二师兄:三种,分别是shared_ptrunique_ptr、和weak_ptr

面试官:说一说三种指针的特征及用途。

二师兄:好的。shared_ptr使用了引用计数(use count)技术,当复制个shared_ptr对象时,被管理的资源并没有被复制,而是增加了引用计数。当析构一个shared_ptr对象时,也不会直接释放被管理的的资源,而是将引用计数减一。当引用计数为0时,才会真正的释放资源。shared_ptr可以方便的共享资源而不必创建多个资源。

二师兄:unique_ptr则不同。unique_ptr独占资源,不能拷贝,只能移动。移动过后的unique_ptr实例不再占有资源。当unique_ptr被析构时,会释放所持有的资源。

二师兄:weak_ptr可以解决shared_ptr所持有的资源循环引用问题。weak_ptr在指向shared_ptr时,并不会增加shared_ptr的引用计数。所以weak_ptr并不知道shared_ptr所持有的资源是否已经被释放。这就要求在使用weak_ptr获取shared_ptr时需要判断shared_ptr是否有效。

struct Boo;
struct Foo{
std::shared_ptr<Boo> boo;
};
struct Boo{
std::shared_ptr<Foo> foo;
};

二师兄:Foo中有一个智能指针指向Goo,而Goo中也有一根智能指针指向Foo,这就是循环引用,我们可以使用weak_ptr来解决这个文通。

Boo boo;
auto foo = boo.foo.lock();
if(foo)
{
//这里通过获取到了foo,可以使用
}else
{
//这里没有获取到,不能使用
}

面试官:好的。智能指针是线程安全的吗?

二师兄:是的。抛开类型T,智能指针是类型安全的。

面试官:为什么?

二师兄:因为智能指针底层使用的引用计数是atomic的原子变量,原子变量在自增自减时是线程安全的,这保证了多线程读写智能指针时是安全的。

面试官:好的。为什么尽量不要使用裸指针初始化智能指针?

二师兄:因为可能存在同一个裸指针初始了多个智能指针,在智能指针析构时会造成资源的多次释放。

面试官:为什么不要从智能指针中返回裸指针呢?

二师兄:是因为如果返回的裸指针被释放了,智能指针持有的资源也失效了,对智能指针的操作是未定义的行为。

面试官:智能指针能够持有数组吗?

二师兄:shread_ptrunique_ptr都可以持有数组。

面试官:那你知道在释放资源的时候两者有什么不同吗?

二师兄:这个暂时还不清楚。。

面试官:可以使用静态对象初始化智能指针吗?

二师兄:让我想想。。不可以,因为静态对象的生命周期和进程一样长,而智能指针的析构的时候会导致静态资源被释放。这会导致未定义的行为。

面试官:如果需要在一个类中实现一个方法,这个方法返回这个类的shread_ptr实例,需要注意哪些东西?

二师兄:需要继承std::enable_shared_from_this类,方法返回shared_from_this()

struct Foo : public std::enable_shared_from_this<Foo>
{
std::shared_ptr<Foo> get_foo()
{
return shared_from_this();
}
};

面试官:为什么不直接返回this指针?

二师兄:额。。。不太清楚,但是这应该是个范式。

面试官:好的,今天的面试结束了,请回去等通知吧。

今天二师兄的表现不错,让我们看看一些回答的不太理想的地方吧。

智能指针是线程安全的吗?

很遗憾,使用不当的时候并不是。

#include <iostream>
#include <memory>
#include <thread>
#include <chrono> struct Foo
{
Foo(int i):i_(i){}
void print() {std::cout << i_ << std::endl;}
int i_;
}; int main(int argc, char const *argv[])
{
{
auto shptr = std::make_shared<Foo>(42);
std::thread([&shptr](){
std::this_thread::sleep_for(std::chrono::seconds(1));
shptr->print();
}).detach();
}
std::this_thread::sleep_for(std::chrono::seconds(2));
return 0;
}
// g++ test.cpp -o test -lpthread
// ./test
// Segmentation fault

当我们向另一个线程传递智能指针的引用时,由于use count并没有加1,在shptr析构时直接销毁了管理的Foo实例,所以在线程中执行shptr->print()会引发coredump

修改起来也很简单,把std::thread([&shptr]()改成std::thread([shptr]()即可。记住,智能指针尽量不要传引用

知道在释放资源的时候shread_ptrunique_ptr有什么不同吗?

这里需要在shared_ptr构造时传入deleter,用来销毁持有的数组,而unique_ptr无需此操作,因为unique_ptr重载了unique_ptr(T[])

get_foo()方法为什么不直接返回this指针?

参考 ”为什么尽量不要使用裸指针初始化智能指针“。聪明的小伙伴,想想如果多次调用get_foo()会发生什么?

好了,今天二师兄的面试之旅到这里就结束了。感谢小伙伴的耐心阅读。如果您觉得还不错,请多多支持二师兄,拜谢~

关注我,带你21天“精通”C++!(狗头)

C++面试八股文:什么是智能指针?的更多相关文章

  1. 【校招面试 之 C/C++】第27题 C++ 智能指针(三)之 unique_ptr

    auto_ptr<string> p1(new string ("auto") : //#1 auto_ptr<string> p2; //#2 p2 = ...

  2. 【校招面试 之 C/C++】第26题 C++ 智能指针(二)之 share_ptr

    1.综述 shared_ptr 是一个标准的共享所有权的智能指针, 允许多个指针指向同一个对象. 定义在 memory 文件中(非memory.h), 命名空间为 std. shared_ptr 是为 ...

  3. 【校招面试 之 C/C++】第25题 C++ 智能指针(一)之 auto_ptr

    1.智能指针背后的设计思想 我们先来看一个简单的例子: void remodel(std::string & str) { std::string * ps = new std::string ...

  4. C++智能指针简单剖析

    导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的问题 ...

  5. 自己动手实现智能指针auto_ptr

    面试的时候,我们经常会被问到如何自己动手实现智能指针auto_ptr.今天我就一边参考STL库中的源代码,一边将auto_ptr的实现敲一遍. auto_ptr归根到底是一个模版类,那么这个类要实现哪 ...

  6. 关于智能指针auto_ptr

    智能指针auto_ptr和shared_ptr也是面试中经常被问到的一个 感觉看auto_ptr的源码反而更加容易理解一些,因为源码的代码量并不大,而且比较容易理解. 本篇主要介绍auto_ptr 其 ...

  7. 【转】C++智能指针简单剖析

    原文链接:http://www.cnblogs.com/lanxuezaipiao/p/4132096.html 导读 最近在补看 <C++ Primer Plus>第六版,这的确是本好书 ...

  8. 【C++】智能指针简单剖析

    转自 http://www.cnblogs.com/lanxuezaipiao/p/4132096.html 导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中 ...

  9. [转]C++智能指针简单剖析

    C++智能指针简单剖析  https://www.cnblogs.com/lanxuezaipiao/p/4132096.html 导读 最近在补看<C++ Primer Plus>第六版 ...

  10. C/C++ 智能指针简单剖析

    导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的问题 ...

随机推荐

  1. jq-ajax-get

    get有三个参数,第一个时候url,第二个是数据,第三个是回调函数(可以用返回值表示,如下所示) 执行正确时,返回的依次是res,type,xhr. 执行错误连接不上的的依次是xhr,type,res ...

  2. 鼎捷ERP二次开发教程 Tiptop GP开发资料大全 Tipto开发实战经验 鼎捷开发实战例子 Tiptop GP二次开发项目例子 4GL开发Demo 鼎捷二次开发完整例子 鼎捷ERP二次开发入门

    本人在ERP实施公司做顾问四五年,参与企业实施ERP十多个项目,非常熟悉企业ERP流程,在实施过程遇到众多问题,提出了不少根据企业具体情况的解决方案. 曾经参与鼎捷Tiptop GP实施十多个项目,具 ...

  3. 最简单Openwrt ipv6配置,局域网WAN6中继模式获取原生ipv6地址

    条件 condition wan 和 wan6 是默认配置     Wan and wan6 are the default configurations 同时wan6可以获取到原生IPv6     ...

  4. pandas之使用自定义函数

    如果想要应用自定义的函数,或者把其他库中的函数应用到 Pandas 对象中,有以下三种方法: 1) 操作整个 DataFrame 的函数:pipe() 2) 操作行或者列的函数:apply() 3)  ...

  5. HTTP.sys漏洞的检测和修复(附补丁包下载)

    关于这个 HTTP.sys 漏洞,查了一些资料,没有一个写的比较全的,下面我来整理下. 这个漏洞主要存在Windows+IIS的环境下,任何安装了微软IIS 6.0以上的Windows Server ...

  6. VMware另一个程序锁定文件的一部分,进程无法访问

    问题描述:搭建RAC11g,在做共享磁盘的时候,节点2要共享节点1的磁盘,但是有一个问题,节点2关机之后,再打开,是有一个访问节点1的磁盘的过程,如果访问失败,就会开不了机器 rac1加的三个磁盘: ...

  7. Java GC基础知识

    对象存活判断 引用计数 在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一:当引用失效时,计数器值就减一:任何时刻计数器为零的对象就是不可 能再被使用的 引用计数法的缺陷: publi ...

  8. 使用Go语言操作HDFS

    HDFS(Hadoop分布式文件系统)是Hadoop生态系统的一部分,它是一个可扩展的分布式文件系统,被设计用于在大规模数据集上运行的应用程序 安装相关package: $ go get github ...

  9. Python用哈希算法查找相似图片(包括不同分辨率,不同大小,不同格式的图片)

    # -*- coding: utf-8 -*- ''' Python用哈希算法查找相似图片并放入[_df]的文件夹中 相似图片包括不同分辨率,不同大小,不同格式,只要图片相似就会算重复文件 安装cv2 ...

  10. islider.js轮播图

    本篇文章地址:https://www.cnblogs.com/Thehorse/p/11601032.html css #iSlider-effect-wrapper { height: 220px; ...