在本文中,我们将讨论C++中的智能指针。什么是智能指针,为什么,以及如何正确使用它们?
指针用于访问程序外部的资源,比如堆内存。因此,为了访问堆内存(如果在堆内存中创建了任何内容),需要使用指针。当访问任何外部资源时,我们只使用该资源的一个副本。如果我们对它做任何更改,我们只需在复制的版本中进行更改。但是,如果我们使用指向资源的指针,我们将能够更改原始资源。
普通指针的问题
看看下面的代码。
C++
#include <iostream> 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 .它会分配越来越多的内存,但不会释放它们,因为我们没有释放它。浪费的内存不能再使用了。这是内存泄漏。整个 堆 因此,记忆可能会变得无用。C++11想出了解决这个问题的办法, 智能指针 .
智能指针的介绍
正如我们所知,无意识地不释放指针会导致内存泄漏,从而导致程序崩溃。Java、C#拥有的语言 垃圾收集机制 聪明地释放未使用的内存以便再次使用。程序员不必担心任何内存泄漏。C++11提出了自己的机制 智能指针 。当对象被销毁时,它也会释放内存。所以,我们不需要像智能指针处理它那样删除它。
A. 智能指针 是指针上的包装器类,其运算符为*和->重载。智能指针类的对象看起来像普通指针。但是,不像 正常指针 它可以释放并释放被破坏的对象内存。
这个想法是带指针上课, 析构函数 和 重载运算符 比如*和->。由于当对象超出作用域时会自动调用析构函数,因此动态分配的内存将自动删除(或者可以减少引用计数)。考虑以下简单 SmartPtr 班
C++
#include <iostream> 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
这只适用于 智力 .那么,我们必须为每个对象创建智能指针?不,有个解决办法, 样板 .如您所见,在下面的代码中 T 可以是任何类型。阅读更多关于 样板 在这里
C++
#include <iostream> using namespace std; // A generic smart pointer class template < class T> 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< int > ptr( new int ()); *ptr = 20; cout << *ptr; return 0; } |
20
注: 智能指针在资源管理中也很有用,比如文件句柄或网络套接字。
智能指针的类型
1.独特的
独特的 只存储一个指针。我们可以通过从指针中删除当前对象来指定不同的对象。注意下面的代码。首先是 唯一_指针 指的是 P1 .但是,然后我们移除 P1 分配 P2 现在指针指向 P2 .
C++14
#include <iostream> using namespace std; #include <memory> 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<Rectangle> P1( new Rectangle(10, 5)); cout << P1->area() << endl; // This'll print 50 // unique_ptr<Rectangle> P2(P1); unique_ptr<Rectangle> P2; P2 = move(P1); // This'll print 50 cout << P2->area() << endl; // cout<<P1->area()<<endl; return 0; } |
5050
2.共享ptr
通过使用 共享ptr 一次可以有多个指针指向这个对象,它将保持 参考计数器 使用 使用_count() 方法
C++14
#include <iostream> using namespace std; #include <memory> 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<Rectangle> P1( new Rectangle(10, 5)); // This'll print 50 cout << P1->area() << endl; shared_ptr<Rectangle> 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; } |
5050502
3.弱ptr
它与shared_ptr更相似,只是它不会维护 参考计数器 .在这种情况下,指针不会在对象上有据点。原因是,如果指针持有该对象并请求其他对象,那么它们可能会形成一个 僵局
C++库以如下形式提供智能指针的实现 自动_ptr , 独特的 , 共享_ptr和弱_ptr
参考资料: http://en.wikipedia.org/wiki/Smart_pointer
本文的改进是 阿米亚兰安罗特 。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请发表评论。 它又被改进了一次 AAShakil50 .