此篇博文,介绍了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对象包含2个int型成员,分别表示长和宽。当这个函数结束后,指针p并没有被销毁,原因是没有调用delete p,这就造成堆区内存浪费。C++程序有个主旨就是“我们不需变量,我们需要内存”。
在main()函数中,fun()函数被无止境的调用,这也就造成了,无止境的创建p,但不去释放p的资源,导致这块内存程序员无法使用,这就叫内存泄漏。C++11为了解决这一问题,提出了智能指针。
每一个C++程序员都会不自觉的犯一种错,那就是创建的指针,忘记手动释放,最后导致程序崩溃。像Java、C#都有自己的垃圾回收机制,去回收不用了的堆区内存,避免出现内存泄漏的问题。C++11也推出了自己的一套机制,那就是智能指针。如果程序员想销毁一个对象时,不需要再调用delete方法了,智能指针会自动将其销毁。
其实智能指针就是一个被封装了的类,封装了一些操作符,如*、->。操作智能指针就和普通指针一样。唯一的区别就是普通指针需要自己手动回收资源。
当智能指针在指定的生命周期结束后,会自动释放内存。
智能指针的封装,可以参考如下代码:
- #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
上面的代码仅仅适用于int类型,如果需要创建任意类型的对象,就需要使用Template,模板编程如下代码:
- #include
- 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
注意:智能指针一般用于管理资源,比如handles和Sockets,如文件句柄、TCP套接字。
unique_ptr存储了单独的一个指针。可以把当前智能指针的对象移除,添加新的对象。如下图所示,unique_pointer P1指向了一个object,只有将P1中的object移除后P2才能指向object。
代码如下:
- #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()< - return 0;
- }
输出:
- 50
- 50
多个shared_ptr可以在同一时间指向1个object,并且提供了计数功能,记录这个对象被多少个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
这个weak_ptr就是shared_ptr的简化版,就是删除了其指向计数的功能。
C++提供的智能指针有4个分别是:auto_ptr、unique_ptr、shared_ptr、weak_ptr
估计是auto_ptr太简单了,所以才没有相关介绍。