C++面试题(四)——智能指针的原理和实现
tanglu2004
http://blog.csdn.net/worldwindjp/
C++面试题(一)、(二)和(三)都搞定的话,恭喜你来到这里,这基本就是c++面试题的最后一波了。
1,你知道智能指针吗?智能指针的原理。
2,常用的智能指针。
3,智能指针的实现。
1答案:智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针。智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放,
2, 最常用的智能指针:
1)std::auto_ptr,有很多问题。 不支持复制(拷贝构造函数)和赋值(operator =),但复制或赋值的时候不会提示出错。因为不能被复制,所以不能被放入容器中。
2) C++11引入的unique_ptr, 也不支持复制和赋值,但比auto_ptr好,直接赋值会编译出错。实在想赋值的话,需要使用:std::move。
例如:
std::unique_ptr<int> p1(new int(5));
std::unique_ptr<int> p2 = p1; // 编译会出错
std::unique_ptr<int> p3 = std::move(p1); // 转移所有权, 现在那块内存归p3所有, p1成为无效的指针.
3) C++11或boost的shared_ptr,基于引用计数的智能指针。可随意赋值,直到内存的引用计数为0的时候这个内存会被释放。
4)C++11或boost的weak_ptr,弱引用。 引用计数有一个问题就是互相引用形成环,这样两个指针指向的内存都无法释放。需要手动打破循环引用或使用weak_ptr。顾名思义,weak_ptr是一个弱引用,只引用,不计数。如果一块内存被shared_ptr和weak_ptr同时引用,当所有shared_ptr析构了之后,不管还有没有weak_ptr引用该内存,内存也会被释放。所以weak_ptr不保证它指向的内存一定是有效的,在使用之前需要检查weak_ptr是否为空指针。
3, 智能指针的实现
下面是一个基于引用计数的智能指针的实现,需要实现构造,析构,拷贝构造,=操作符重载,重载*-和>操作符。
1 template <typename T> 2 class SmartPointer { 3 public: 4 //构造函数 5 SmartPointer(T* p=0): _ptr(p), _reference_count(new size_t){ 6 if(p) 7 *_reference_count = 1; 8 else 9 *_reference_count = 0; 10 } 11 //拷贝构造函数 12 SmartPointer(const SmartPointer& src) { 13 if(this!=&src) { 14 _ptr = src._ptr; 15 _reference_count = src._reference_count; 16 (*_reference_count)++; 17 } 18 } 19 //重载赋值操作符 20 SmartPointer& operator=(const SmartPointer& src) { 21 if(_ptr==src._ptr) { 22 return *this; 23 } 24 releaseCount(); 25 _ptr = src._ptr; 26 _reference_count = src._reference_count; 27 (*_reference_count)++; 28 return *this; 29 } 30 31 //重载操作符 32 T& operator*() { 33 if(ptr) { 34 return *_ptr; 35 } 36 //throw exception 37 } 38 //重载操作符 39 T* operator->() { 40 if(ptr) { 41 return _ptr; 42 } 43 //throw exception 44 } 45 //析构函数 46 ~SmartPointer() { 47 if (--(*_reference_count) == 0) { 48 delete _ptr; 49 delete _reference_count; 50 } 51 } 52 private: 53 T *_ptr; 54 size_t *_reference_count; 55 void releaseCount() { 56 if(_ptr) { 57 (*_reference_count)--; 58 if((*_reference_count)==0) { 59 delete _ptr; 60 delete _reference_count; 61 } 62 } 63 } 64 }; 65 66 int main() 67 { 68 SmartPointer<char> cp1(new char(‘a‘)); 69 SmartPointer<char> cp2(cp1); 70 SmartPointer<char> cp3; 71 cp3 = cp2; 72 cp3 = cp1; 73 cp3 = cp3; 74 SmartPointer<char> cp4(new char(‘b‘)); 75 cp3 = cp4; 76 }