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();
    }
}

函数fun生成一个指针指向Rectangle对象。Rectangle由两个整数length和breadth组成。因为p是一个局部变量,当函数fun结束时,它将被销毁。然而,因为我们忘记在函数结束时使用delete p;,它消耗的内存不会被释放。这意味着内存将不能被其他资源使用。然而,我们不再需要这个变量,而是需要释放内存。

在主函数中,函数fun在一个无限循环中被调用。这意味着它将持续生成p。它将分配更多的内存,但不会释放它,因为我们没有释放它。未使用的内存无法再次使用。这会导致内存泄漏。因此,整个堆内存可能变得无用。C++11的智能指针为这个问题提供了解决方案。

智能指针正在被引入

不自觉地,没有释放指针会导致内存泄漏,这可能导致程序崩溃。Java和C#语言使用垃圾回收机制智能地释放未使用的内存,以便可以再次使用它。程序员不必担心内存泄漏。智能指针是C++11开发的一种机制。当对象被销毁时,内存也被释放。因此,我们不需要删除它,因为智能指针将处理它。

智能指针是一个包装指针的类,它有像*和->这样重载的操作符。智能指针类的对象类似于普通指针。然而,与普通指针不同,它有回收和释放被销毁对象内存的能力。

考虑一个有指针、析构函数和重载操作符的类。因为析构函数在对象退出作用域时自动调用,动态分配的内存将被删除(或引用计数可以递减)。考虑下面的SmartPtr类。

C++代码

#include 
using namespace std;

class SmartPtr {
    int* ptr; // Actual pointer
public:
    // 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

这仅适用于int。那么我们需要为每个对象创建一个智能指针吗?不需要,模板,有一个解决办法。如下面的代码所示,T可以是任何类型。点击这里了解更多有关模板的信息。

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 dereferencing 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

unique ptr 中只存储一个指针。通过将当前对象从指针中移除,我们可以赋予一个不同的对象。请注意下面的代码。首先,unique_pointer 指向 P1。然而,我们移除了 P1 并用 P2 替换它,所以指针现在指向 P2。

C++ 智能指针

C++代码

#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()方法来保持引用计数。

C++ 智能指针

C++代码

#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++ 智能指针

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程