对于C++11的智能指针,每年考到的概率是很大的,如下,但是考的概率大不代表就非常难。但是又很喜欢放在面试的最后才出现,所以对心理素质不好的考生非常不友好,可能前面已经被问懵了,到智能指针的时候就全都忘记了,考题都是有模板可以套的,相信看完这几篇文章智能指针这块满分在手!!!
目录
这边考查智能指针大概有几种问法:
可能问法一:
智能指针普遍所用到的是什么原理,你所学过的智能指针的底层有那些是属于应用的这种原理的,那些不是呀,请简述!!!
问题解析:
一看到这个问法就知道是两个问题,借着问智能指针底层原理在考你对你所学过的智能指针的初步掌握情况。
答题格式:
原理1:主要的就是就是新名词RAII技术,不是RALL
为了我们方便面试的时候可以讲出来,可以简化成下面的版本(我自己写的)
//RAII(智能指针的基本原理)(模拟成指针对象):指的是资源获得及初始化,利用对象生命周期来控制程序资源
//让一个类对象帮我保存管理这个资源,不用自己初始化了,在生命周期内始终有效,生命周期结束
//之后自动释放,可以解决内存泄露的问题
//相当于把一个资源托管给一个对象
//好处:
//不用自己手动释放空间
//在生命周期范围内始终有效,避免异常
智能指针,如果可以自动释放空间算智能的话,那智能的问题就解决了,但是指针怎么说呢,所以还需要解释一下为什么是指针。
原理2:具备指针的行为,可以通过operator*或者operator->访问管理空间的元素。
那么我们前半个问题就解决了,然后开始考虑后半个问题。
由于我只重点学过auto_ptr,unique_ptr,shared_ptr,weak_ptr,所以只能以认知范围内认为,前面三个都遵循RAII原理,最后这个weak_ptr不遵循RAII原理,因为weak_ptr研发出来本质是为了解决循环引用导致内存泄露的问题。
可能问法2:
你知道auto_ptr,unique_ptr,shared_ptr吗,请叙述一下他们的区别。
问题分析:
这问题主要考察的就是对于这三个满足RAII的智能指针的基本用法,属于简单偏上的题的范畴,只要在面试前很熟悉这些指针的用法及差别就不会难了,我们下面通过三段代码的形式边演示边总结。
解答代码:
struct Date
{
int _year;
int _month;
int _day;
Date(int year = 1, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{}
~Date()
{
cout << "~Date()" << endl;
}
};
先定义一个Date类,使得被管理的对象可以有资源可以释放。
int main()
{
auto_ptr<Date> ap1(new Date);//C++11已经全面禁止使用auto_ptr了
ap1->_year++;
cout << ap1->_year << endl;
auto_ptr<Date> ap2(ap1);
//拷贝时,管理权限转移,被拷贝悬空
//auto_ptr 转移所有权后,虽然 ap1 被置为 nullptr,但这并不意味着对象的内存被立即释放。被管理的对象仍然由 sp2 管理,内存暂时没有释放,如果你在这时尝试访问 ap1,指向的内存仍然存在,但这并不是安全的做法。Visual Studio 编译器并没有做特别的“优化”来支持这种行为,
//而是因为内存管理机制没有立即覆盖或清除该区域,导致指针仍能访问。
//根据上面我们实现的smart_ptr的基本逻辑就是auto_ptr
//所以不建议使用这个
//ap1->_year++;//ap1变成野指针了
unique_ptr<Date> sp3(new Date);//这个不支持拷贝
//unique_ptr<Date> sp1(sp3);//可以看出unique_ptr已经不支持拷贝了(不支持将别人管理的空间拷贝给自己,使自己也可以管理他)
vector<unique_ptr<Date>> v;//unique_ptr<Date>是一种数据类型
shared_ptr<Date> sp4(new Date);//share_ptr支持拷贝,所以功能比较多
shared_ptr<Date> sp5(sp4);
shared_ptr<Date> sp6(sp4);
cout << sp4.use_count() << endl;//use_count的作用是计算一个资源受到多少个智能指针管理
return 0;
}
不同类型的智能指针不能互相拷贝。
template<class T>
struct DeleteArray
{
void operator()(T* ptr)
{
cout << "DeleteArray" << endl;
delete[] ptr;//一下子删除多个对象需要加上[]
}
};
struct Fclose
{
void operator()(FILE* ptr)
{
cout << "operator()(FILE* ptr)" << endl;
fclose(ptr);
}
};
int main()
{
// C++11
//unique_ptr<Date> up1(new Date);
//不支持拷贝
//unique_ptr<Date> up2(up1);
//但是由于智能指针需要释放资源,所以可以定制删除器
//unique_ptr的定制删除器可以使用仿函数也可以使用lambda,因为定制删除器的原理就是仿函数,lambda的本质也是仿函数,且在调用时在模板参数中体现,而不是在函数体
unique_ptr<Date, DeleteArray<Date>> sp1(new Date[5]);//定制删除器是删除智能指针管理的对象不是智能指针本身
unique_ptr<Date[]> sp2(new Date[5]);//特殊写法,当开辟多个空间时可以这么写定制删除器
//这个就是由于定义顺序么,栈区先进后出,先定义的后析构
unique_ptr<FILE, Fclose> up3(fopen("test.cpp", "w"));
return 0;
}
int main()
{
//vector<shared_ptr<Date>> v;//智能指针可以看成一种类型
//share_ptr也可以使用定制删除器的,但是这时就是放在函数体部分, 作为一个函数进行调用,当然也可以写成lambda,这里就不做更多的演示了。
shared_ptr<FILE> sp1(fopen("test.txt", "w"), Fclose());
shared_ptr<Date[]> sp2(new Date[5]);//这种特殊写法同样适用
//make_shared的作用是通过传入的参数包(args)先构建一个可以通过shared_ptr管理的对象然后再交给一个shared_ptr对象管理
shared_ptr<Date> sp3 = make_shared<Date>(2024, 2, 3);//使用时需要传模板类型
return 0;
}
所以经过上面的演示可以得出结论!!!
答题格式:
其实主要就是从支不支持拷贝,定制删除器怎么样,释放资源的规则是怎么样的,自身还有什么优势和不足进行答题。其他的比如use_count,operator->的作用可答可不答。
可能问法三:
你知道weak_ptr吗,和shared_ptr有什么区别,请简述一下weak_ptr的功能。
问题分析
这个问题其实之前或多或少的提过,我们肯定是知道的,weak_ptr和shared_ptr的区别就是weak_ptr不支持RAII,不支持直接管理资源,为什么是直接呢,后面会讲,所以不能认为其不能管理资源,自然功能就不能向着RAII这方面答了,那功能就这剩下能解决shared_ptr循环引用导致内存泄露的问题。
预知后事如何,请持续关注!!!!!!!!!!!!!!!!!!!!!!!!!!