📜  C++中智能指针及其类型的介绍

📅  最后修改于: 2021-05-30 07:29:06             🧑  作者: Mango

本文要学习的内容:

  1. 指针在C / C++中的重要性。
  2. 普通指针出现问题。
  3. 为什么引入智能指针。
  4. 智能指针的类型。

指针在C / C++中的重要性:
指针用于访问程序外部的资源,例如堆内存。因此,如果在堆内存中创建了任何东西,则用于访问堆内存。

普通指针出现问题:
通过使用此示例,使用小型C++程序,让我们了解普通指针的主要问题是什么。

#include 
using namespace std;
  
class Rectangle {
private:
    int length;
    int breadth;
};
  
void fun()
{
    // By taking a pointer p and
    // dynamically creating object
    // of class rectangle
    Rectangle* p = new Rectangle();
}
  
int main()
{
    // Infinite Loop
    while (1) {
        fun();
    }
}

因此,发生的事情是它将有一个指针“ p”,这将指向一个矩形类型的对象,该对象将具有长度和宽度。一旦函数结束,将删除该“ p”,因为p是函数的局部变量,该变量将终止,但是在堆内部分配的新矩形不会被释放。它将返回并再次返回它的无限循环,因此将再次创建新的p,然后再次为长度和宽度相同的矩形创建一个新的对象。那么,关于前一个对象的情况将不会被删除,对于额外的新对象,也将不会被删除。因此,每次它都会创建一个对象,但不会删除它,因此这会导致堆内存中的内存泄漏。就像内存的长度和宽度一样,虽然已分配但未使用,但未使用。因此,整个堆内存可能是无限的,因此可能变得不可用。因此,在某一阶段,由于缺少堆内存,程序将崩溃。因此,在fun()的最后,如果我们不提及这一点,则应使用’delete p’,这将导致非常严重的问题。因此,由于程序员的懒惰或粗心,可能会出现这种类型的问题。因此,为了帮助程序员C++ 11承担责任并引入了智能指针。

智能指针介绍
堆内存的问题在于,当不需要它时,必须将其自身释放。因此,大多数程序员在编写用于对象的重新分配的代码时过于懒惰,这会导致严重的问题,例如内存泄漏,这将导致程序崩溃。因此, Java,C#、. Net Framework之类的语言提供了垃圾回收机制来取消分配未使用的对象。因此,在C++ 11中,它引入了自动管理内存的智能指针,当指针不在作用域内时,它们将在不使用时自动释放对象,从而自动释放内存。

考虑以下带有普通指针的简单C++代码。

MyClass* ptr = new MyClass();
ptr->doSomething();
// We must do delete(ptr) to avoid memory leak

使用智能指针,我们可以使指针以不需要显式调用delete的方式工作。智能指针是指针的包装类,带有*和->重载的运算符。智能指针类的对象看起来像一个指针,但是可以执行普通指针不喜欢自动销毁的许多事情(是的,我们不必显式使用delete),引用计数等等。
这个想法是采用带有指针,析构函数和重载运算符(例如*和->)的类。由于当对象超出范围时会自动调用析构函数,因此动态分配的内存将自动删除(或可以减少引用计数)。考虑以下简单的智能ptr类。

#include 
using namespace std;
  
class SmartPtr {
    int* ptr; // Actual pointer
public:
    // Constructor: Refer https:// www.geeksforgeeks.org/g-fact-93/
    // for use of explicit keyword
    explicit SmartPtr(int* p = NULL) { ptr = p; }
  
    // Destructor
    ~SmartPtr() { delete (ptr); }
  
    // Overloading dereferencing operator
    int& operator*() { return *ptr; }
};
  
int main()
{
    SmartPtr ptr(new int());
    *ptr = 20;
    cout << *ptr;
  
    // We don't need to call delete ptr: when the object
    // ptr goes out of scope, the destructor for it is automatically
    // called and destructor does delete ptr.
  
    return 0;
}
输出:
20

编写一个适用于所有类型的智能指针类。
是的,我们可以使用模板编写通用的智能指针类。以下C++代码演示了相同的过程。

#include 
using namespace std;
  
// A generic smart pointer class
template 
class SmartPtr {
    T* ptr; // Actual pointer
public:
    // Constructor
    explicit SmartPtr(T* p = NULL) { ptr = p; }
  
    // Destructor
    ~SmartPtr() { delete (ptr); }
  
    // Overloading dereferncing operator
    T& operator*() { return *ptr; }
  
    // Overloading arrow operator so that
    // members of T can be accessed
    // like a pointer (useful if T represents
    // a class or struct or union type)
    T* operator->() { return ptr; }
};
  
int main()
{
    SmartPtr ptr(new int());
    *ptr = 20;
    cout << *ptr;
    return 0;
}
输出:
20

注意:智能指针在资源管理(例如文件句柄或网络套接字)中也很有用。

智能指针的类型:

  1. unique_ptr
    如果使用唯一的指针,则如果创建了一个对象并且指针P1指向该对象,则只有一个指针可以一次指向该对象。因此,我们无法与其他指针共享,但是可以通过删除P1将控件转移到P2。

    #include 
    using namespace std;
    #include 
      
    class Rectangle {
        int length;
        int breadth;
      
    public:
        Rectangle(int l, int b)
        {
            length = l;
            breadth = b;
        }
      
        int area()
        {
            return length * breadth;
        }
    };
      
    int main()
    {
      
        unique_ptr P1(new Rectangle(10, 5));
        cout << P1->area() << endl; // This'll print 50
      
        // unique_ptr P2(P1);
      
        unique_ptr P2;
        P2 = move(P1);
      
        // This'll print 50
        cout << P2->area() << endl;
      
        // cout<area()<
    输出:
    50
    50
    
  2. shared_ptr
    如果您使用shared_ptr,则一次可以有多个指针指向该对象,并且它将使用use_count()方法维护一个引用计数器
    #include 
    using namespace std;
    #include 
      
    class Rectangle {
        int length;
        int breadth;
      
    public:
        Rectangle(int l, int b)
        {
            length = l;
            breadth = b;
        }
      
        int area()
        {
            return length * breadth;
        }
    };
      
    int main()
    {
      
        shared_ptr P1(new Rectangle(10, 5));
        // This'll print 50
        cout << P1->area() << endl;
      
        shared_ptr P2;
        P2 = P1;
      
        // This'll print 50
        cout << P2->area() << endl;
      
        // This'll now not give an error,
        cout << P1->area() << endl;
      
        // This'll also print 50 now
        // This'll print 2 as Reference Counter is 2
        cout << P1.use_count() << endl;
        return 0;
    }
    
    输出:
    50
    50
    50
    2
    
  3. weak_ptr
    它与shared_ptr非常相似,只不过它不维护引用计数器。在这种情况下,指针将不会对对象产生强烈的影响。原因是,如果假设指针持有该对象并请求其他对象,则它们可能会形成死锁。

C++库以auto_ptr,unique_ptr,shared_ptr和weak_ptr的形式提供智能指针的实现

参考:
http://en.wikipedia.org/wiki/Smart_pointer

要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”