本文要学习的内容:
- C/C++中指针的重要性。
- 普通指针出现问题。
- 为什么引入智能指针。
- C++智能指针的类型。
C/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是函数的局部变量, 它将终止, 但是在堆内部分配的新矩形不会被释放。它将返回并再次返回它的无限循环, 因此将再次创建新的p, 然后再次为长度和宽度相同的矩形创建新的对象。因此, 关于先前的对象, 它将不会被删除;对于额外的新对象, 也将不会被删除。因此, 每次它都会创建一个对象, 但不会删除它, 因此会导致堆内存中的内存泄漏。就像长度和宽度的内存一样, 虽然已分配但未使用, 但未使用。如此一来, 整个堆内存可能会因为无限而无法使用。因此, 在某一阶段, 由于缺少堆内存, 程序将崩溃。因此, 在fun()的最后, 如果我们不提及这一点, 则应使用"删除p", 这将导致非常严重的问题。因此, 由于程序员的懒惰或粗心, 可能会出现这种类型的问题。因此, 为了帮助程序员C++ 11承担责任并引入了智能指针。
C++智能指针介绍
堆内存的问题是,当你不需要它时,您必须释放它自己。因此,大多数程序员都太懒于编写对象释放代码,这导致了严重的问题,如内存泄漏,将导致程序崩溃。
所以像Java, c#,.net框架这样的语言,它们提供了一个垃圾回收机制来释放不使用的对象。在c++ 11中,它引入了智能指针自动管理内存它们会在不使用时释放对象当指针超出作用域时,它会自动释放内存。
考虑以下带有普通指针的简单C++代码。
MyClass* ptr = new MyClass();
ptr->doSomething();
//We must do delete(ptr) to avoid memory leak
使用C++的智能指针, 我们可以使指针以无需显式调用delete的方式工作。智能指针是指针的包装类, 带有*和->重载的运算符。
智能指针类的对象看起来像一个指针, 但是可以完成普通指针无法完成的许多自动销毁操作(是的, 我们不必显式使用delete), 引用计数等。
其思想是接受带有指针、析构函数和重载操作符(如*和->)的类。由于析构函数在对象超出作用域时自动调用,动态分配的内存将自动删除(或者引用计数可以递减)。考虑以下简单的智能ptr类。
#include <iostream>
using namespace std;
class SmartPtr {
int * ptr; //Actual pointer
public :
//Constructor: Refer https://www.lsbin.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++智能指针类型。
是的, 我们可以使用模板来编写泛型智能指针类。下面的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 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<int> ptr( new int ());
*ptr = 20;
cout <<*ptr;
return 0;
}
输出如下:
20
注意:智能指针在资源管理中也很有用, 例如文件句柄或网络套接字。
C++中智能指针的类型:
unique_ptr
如果你使用唯一的指针, 则如果创建了一个对象并且指针P1指向该对象, 则只有一个指针可以一次指向该对象。因此我们无法与其他指针共享, 但是我们可以通过删除P1将控件转移到P2。
#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;
}
输出如下:
50
50
shared_ptr
如果你正在使用shared_ptr,那么一次可以有多个指针指向这个对象,它将使用use_count()方法维护一个引用计数器。
#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;
}
输出如下:
50
50
50
2
weak_ptr
它与shared_ptr非常相似,只是它不维护引用计数器。在这种情况下,指针对对象没有很强的控制作用。原因是,如果假设指针持有对象并请求其他对象,那么它们可能会形成死锁。
C++库以以下形式提供C++智能指针的实现:auto_ptr, unique_ptr, shared_ptr和weak_ptr
参考文献:
http://en.wikipedia.org/wiki/Smart_pointer
这篇文章的改进之处在于AmiyaRanjanRout。如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请写评论。