面试题目3:
-
智能指针有哪些 ?share 和unique有什么区别?如何实现一个unique?
概念:智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针。智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放.即将基本类型指针封装为类对象指针(这个类肯定是个模板,以适应不同基本类型的需求),并在析构函数里编写delete语句删除指针指向的内存空间。
目的:避免资源泄露。常见的几种:auto_ptr,shared_ptr,unique_ptr,weak_ptr,
auto_ptr:
摒弃auto_ptr的原因,一句话总结就是:避免潜在的内存崩溃问题
auto_ptr films[5] =
{
auto_ptr (new string(“Fowl Balls”)),
auto_ptr (new string(“Duck Walks”)),
auto_ptr (new string(“Chicken Runs”)),
auto_ptr (new string(“Turkey Errors”)),
auto_ptr (new string(“Goose Eggs”))
};
auto_ptr pwin;
pwin = films[2]; // films[2] loses ownership. 将所有权从films[2]转让给pwin,此时films[2]不再引用该字符串从而变成空指针
cout << “The nominees for best avian baseballl film are\n”;
for(int i = 0; i < 5; ++i)
cout << *films[i] << endl;
cout << "The winner is " << *pwin << endl;
unique_ptr:
unique_ptr实现了独占式拥有概念,意味着它可确保一个对象和其相应资源同一时间只被一个指针拥有。一旦拥有者被销毁或变成空,或开始拥有另一个对象,先前拥有的那个对象就会被销毁,其任何相应资源也会被释放。
{
std::unique_ptr uptr(new int(10)); //绑定动态对象
//std::unique_ptr uptr2 = uptr; //不能賦值
//std::unique_ptr uptr2(uptr); //不能拷貝
std::unique_ptr uptr2 = std::move(uptr); //轉換所有權
uptr2.release(); //释放所有权
}
//超過uptr的作用域,內存釋放
shared_ptr:
shared_ptr则允许多个指针指向同一个对象,实现基于引用计数技术。
智能指针管理的着一个对象,并记录着所有管理同个对象的指针个数,这个个数称为计数。藉由智能指针去初始化或赋值其他智能指针时,计数的值增加1,表示资源对象多了一个引用;当智能指针的生命周期结束或者指向别的对象时,计数的值减去1,表示资源对象减少一个引用。智能指针生命周期结束时,编译器会调用它的析构函数,在析构函数中判断引用计数的值是否为0,若为0,则释放所管理的对象资源;若不为0,表明还有其他指针指向所管理的对象,不释放该对象资源。
int *p = new int(30);
std::shared_ptr bptr§;//方式1
std::shared_ptr aptr = std::make_shared(20);//方式
std::shared_ptr cptr(aptr);
std::cout << “aptr.use_count() = " << aptr.use_count() <<” value = "<<*aptr<<std::endl;//use_count 是引用计数器
std::cout << “bptr.use_count() = " << bptr.use_count() <<” value = "<<*bptr<<std::endl;
std::cout << “cptr.use_count() = " << cptr.use_count() <<” value = "<<*cptr<<std::endl;
//输出是:2,20
// 1,30
// 2,20
如何选择:
(1)如果程序要使用多个指向同一个对象的指针,应选择shared_ptr。这样的情况包括:
有一个指针数组,并使用一些辅助指针来标示特定的元素,如最大的元素和最小的元素;
两个对象包含都指向第三个对象的指针;
STL容器包含指针。很多STL算法都支持复制和赋值操作,这些操作可用于shared_ptr,但不能用于unique_ptr(编译器发出warning)和auto_ptr(行为不确定)。如果你的编译器没有提供shared_ptr,可使用Boost库提供的shared_ptr。
(2)如果程序不需要多个指向同一个对象的指针,则可使用unique_ptr。如果函数使用new分配内存,并返还指向该内存的指针,将其返回类型声明为unique_ptr是不错的选择。这样,所有权转让给接受返回值的unique_ptr,而该智能指针将负责调用delete。可将unique_ptr存储到STL容器在那个,只要不调用将一个unique_ptr复制或赋给另一个算法(如sort())。例如,可在程序中使用类似于下面的代码段。
如何实现shared_ptr:
template<class T,class Del>
class SharePtr
{
public:
SharePtr(T* ptr) //构造函数
: _ptr(ptr), _ref(new int(1))
{
cout << “SharePtr(T* ptr)” << endl;
}
SharePtr( SharePtr& sp) //拷贝构造函数
{
cout <<“SharePtr( SharePtr& sp)” << endl;
_ptr = sp._ptr;
_ref = sp._ref;
(_ref)++;
}
~SharePtr() //析构函数
{
Release();
}
void Release()
{
if (–(_ref) == 0)
{
delete _ref;
_del(_ptr);
}
}
T* operator->() //箭头操作符的重载
{
return _ptr;
}
T& operator*() //解引用操作符重载
{
return _ptr;
}
SharePtr& operator=(SharePtr& sp) //赋值操作符的重载
{
if (_ptr != sp._ptr)
{
Release();
_ptr = sp._ptr;
_ref = sp._ref;
(_ref)++;
}
return this;
}
private:
T _ptr;
int* _ref;
Del _del; //-----这是一个对象函数决定着析构时以什么方式释放申请的空间
};
- vector 什么时候会失效?list会失效?
- 虚函数和纯虚函数区别?
- 单例模式怎么实现?设计模式
- 多线程开发需要注意哪些?
7.进程间的通信方式,及特点
8.C++新特性,lanmda表达式,
9.vector的push_back 可以用什么替代?
10.生产和消费模型
11.内存里空间分配
12.static作用
13.继承中如何判断类型是子类还是父类
14.程序挂了如何调试
15.栈和队列相互实现 - 二叉树
- 规范的编程
18.深复制和浅复制
19.fork
20.strcmp,strcpy,memmove实现