zoukankan      html  css  js  c++  java
  • C++面试题(四)——智能指针的原理和实现

    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, 智能指针的实现

          下面是一个基于引用计数的智能指针的实现,需要实现构造,析构,拷贝构造,=操作符重载,重载*-和>操作符。

        template <typename T>
        class SmartPointer {
        public:
            //构造函数
            SmartPointer(T* p=0): _ptr(p), _reference_count(new size_t){
                if(p)
                    *_reference_count = 1;
                else
                    *_reference_count = 0;
            }
            //拷贝构造函数
            SmartPointer(const SmartPointer& src) {
                if(this!=&src) {
                    _ptr = src._ptr;
                    _reference_count = src._reference_count;
                    (*_reference_count)++;
                }
            }
            //重载赋值操作符
            SmartPointer& operator=(const SmartPointer& src) {
                if(_ptr==src._ptr) {
                    return *this;
                }
                releaseCount();
                _ptr = src._ptr;
                _reference_count = src._reference_count;
                (*_reference_count)++;
                return *this;
            }
         
            //重载操作符
            T& operator*() {
                if(ptr) {
                    return *_ptr;
                }
                //throw exception
            }
            //重载操作符
            T* operator->() {
                if(ptr) {
                    return _ptr;
                }
                //throw exception
            }
            //析构函数
            ~SmartPointer() {
                if (--(*_reference_count) == 0) {
                    delete _ptr;
                    delete _reference_count;
                }
            }
        private:
            T *_ptr;
                size_t *_reference_count;
                void releaseCount() {
                if(_ptr) {
                    (*_reference_count)--;
                        if((*_reference_count)==0) {
                            delete _ptr;
                            delete _reference_count;
                        }
                }
                }
        };
         
        int main()
        {
            SmartPointer<char> cp1(new char('a'));
            SmartPointer<char> cp2(cp1);
            SmartPointer<char> cp3;
            cp3 = cp2;
            cp3 = cp1;
            cp3 = cp3;
            SmartPointer<char> cp4(new char('b'));
            cp3 = cp4;
        }


    ————————————————
    版权声明:本文为CSDN博主「tanglu2004」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/worldwindjp/article/details/18843087

  • 相关阅读:
    JS中所有数组的方法和所有的对象方法,包含ES5和ES6
    (原创!)彻底理解JS中的事件,事件处理函数,钩子函数,回调函数。
    深拷贝和浅拷贝的区别,object.assgin方法是深拷贝还是浅拷贝
    axios,Ajax,jQuery ajax,axios和fetch的区别
    python : 文档比较
    leetcode——989.数组形式的整数加法
    leetcode——66.加一
    leetcode——283.移动0
    leetcode——27.移除元素
    leetcode刷题第一天——两数之和
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14490176.html
Copyright © 2011-2022 走看看