面试题目3:智能指针

1.  智能指针有哪些 ?share 和unique有什么区别?如何实现一个unique?

         概念:智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针。智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放.即将基本类型指针封装为类对象指针(这个类肯定是个模板,以适应不同基本类型的需求),并在析构函数里编写delete语句删除指针指向的内存空间。

       目的:避免资源泄露。

 

          常见的几种:auto_ptr,shared_ptr,unique_ptr,weak_ptr,

 

auto_ptr:

      摒弃auto_ptr的原因,一句话总结就是:避免潜在的内存崩溃问题

      auto_ptr<string> films[5] = {   auto_ptr<string> (new string("Fowl Balls")),   auto_ptr<string> (new string("Duck Walks")),   auto_ptr<string> (new string("Chicken Runs")),   auto_ptr<string> (new string("Turkey Errors")),   auto_ptr<string> (new string("Goose Eggs"))  };  auto_ptr<string> 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<int> uptr(new int(10));  //绑定动态对象

        //std::unique_ptr<int> uptr2 = uptr;  //不能賦值

        //std::unique_ptr<int> uptr2(uptr);  //不能拷貝

        std::unique_ptr<int> uptr2 = std::move(uptr); //轉換所有權

        uptr2.release(); //释放所有权

      }

    //超過uptr的作用域,內存釋放

 

shared_ptr:

shared_ptr则允许多个指针指向同一个对象,实现基于引用计数技术。

       智能指针管理的着一个对象,并记录着所有管理同个对象的指针个数,这个个数称为计数。藉由智能指针去初始化或赋值其他智能指针时,计数的值增加1,表示资源对象多了一个引用;当智能指针的生命周期结束或者指向别的对象时,计数的值减去1,表示资源对象减少一个引用。智能指针生命周期结束时,编译器会调用它的析构函数,在析构函数中判断引用计数的值是否为0,若为0,则释放所管理的对象资源;若不为0,表明还有其他指针指向所管理的对象,不释放该对象资源。

     

int *p = new int(30);

    std::shared_ptr<int> bptr(p);//方式1

    std::shared_ptr<int> aptr = std::make_shared<int>(20);//方式

    std::shared_ptr<int> 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。这样的情况包括:

(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;            //-----这是一个对象函数决定着析构时以什么方式释放申请的空间

};

 

3.  vector 什么时候会失效?list会失效?

4.  虚函数和纯虚函数区别?

5.  单例模式怎么实现?设计模式

6. 多线程开发需要注意哪些?

7.进程间的通信方式,及特点

8.C++新特性,lanmda表达式,

9.vector的push_back 可以用什么替代?

10.生产和消费模型

11.内存里空间分配

12.static作用

13.继承中如何判断类型是子类还是父类

14.程序挂了如何调试

15.栈和队列相互实现

16. 二叉树

17. 规范的编程

18.深复制和浅复制

19.fork 

20.strcmp,strcpy,memmove实现

posted @ 2019-03-13 18:33  Kiris  阅读(873)  评论(0编辑  收藏  举报