某日二师兄参加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. QML和QT

    推荐一些学习qml教程 Qt官方的QML教程: https://doc.qt.io/qt-5/qtqml-index.html,这是一个由Qt官方提供的完整的QML教程,包含了所有基本知识和高级语法. ...

  2. MySQL约束条件介绍

    无符号.零填充 unsigned # 因为正负值符号会占用一个比特位,使用此约束条件可以去掉数字类型里面的正负值符号,之后相同数字类型会支持的正数范围会更大 id int unsigned zerof ...

  3. day3 函数的定义和调用,练习编写简单的程序(记录1)

    一.函数的定义 可以分为以下两种: 1.函数声明和函数定义分离 这种方法将函数声明和函数定义分开,通常在头文件中先声明函数原型,然后在源文件中实现函数定义. 例如,头文件 example.h 中声明了 ...

  4. [Linux]常用命令之【top/uptime/w/vmstat/free】

    1 top 语法:top [-s time] [-d count] [-q] [-u] [-h] [-n number] [-f filename] -s time 设置屏幕刷新的延时,单位为秒,默认 ...

  5. 粘包,自定义协议,struct模块,粘包解决终极大招

    粘包: 1.粘包问题出现的原因: (udp不会出现粘包问题) 1.1.tcp是流式协议,数据像水流一样黏在一起,没有任何边界区分 1.2.收数据没收干净,有残留,就会下一次结果混淆在一起去(客户端接受 ...

  6. py文件转换为so文件

    将py文件编译为so文件 利用上面代码生成so文件生成的文件不方便取放,名字也不一样 通过执行发现转换执行了下面三句 /usr/local/python3/bin/cython test.py gcc ...

  7. [Pytorch框架] 4.1 Fine tuning 模型微调

    文章目录 4.1 Fine tuning 模型微调 4.1.1 什么是微调 为什么要微调 迁移学习 Transfer Learning 二者关系 4.1.2 如何微调 4.1.3 注意事项 4.1.3 ...

  8. 用Python语言进行时间序列ARIMA模型分析

    应用时间序列 时间序列分析是一种重要的数据分析方法,应用广泛.以下列举了几个时间序列分析的应用场景: 1.经济预测:时间序列分析可以用来分析经济数据,预测未来经济趋势和走向.例如,利用历史股市数据和经 ...

  9. [python] Python类型提示总结

    Python3.5 版本引入了类型提示(Type Hints),它允许开发者在代码中显式地声明变量.函数.方法等的类型信息.这种类型声明不会影响 Python 解释器的运行,但可以让 IDE 和静态分 ...

  10. 2023-04-13:给定一个字符串数组strs,其中每个字符串都是小写字母组成的, 如果i < j,并且strs[i]和strs[j]所有的字符随意去排列能组成回文串, 那么说(i,j)叫做一个互补

    2023-04-13:给定一个字符串数组strs,其中每个字符串都是小写字母组成的, 如果i < j,并且strs[i]和strs[j]所有的字符随意去排列能组成回文串, 那么说(i,j)叫做一 ...