程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 實戰c++中的智能指針unique_ptr系列

實戰c++中的智能指針unique_ptr系列

編輯:關於C++

今天遇到一個錯誤,是關於unique_ptr的get方法的,忽略了。

之前博客是這樣寫get方法的:
其中bar是一個智能指針,p是一個普通指針:

p = bar.get(); 後,bar並非被釋放,也就相當於指針p和智能指針bar共同管理一個對象,所以就*p做的一切,都會反應到bar指向的對象上。

那麼來看今天的代碼:

#include
#include
class Widget {
public:
    Widget() { std::cout << "Widget::Widget()" << std::endl; }
    virtual ~Widget() { std::cout << "Widget::~Widget()" << std::endl; }
    virtual void draw() = 0;
};

class WindowsButton : public Widget {
public:
    WindowsButton() = default;
    ~WindowsButton() = default;
    void draw() { std::cout << "WindowsButton" << std::endl; }
};

int main() {
     std::unique_ptr w = std::unique_ptr(new WindowsButton());
     w.get()->draw();
     w->draw();
}

輸出:
Widget::Widget()
WindowsButton
WindowsButton
Widget::~Widget()

就是使用w.get()和直接使用w是一樣的效果!

現在就要玩點花樣了:

#include
#include
class Widget {
public:
    Widget() { std::cout << "Widget::Widget()" << std::endl; }
    virtual ~Widget() { std::cout << "Widget::~Widget()" << std::endl; }
    virtual void draw() = 0;
};

class WindowsButton : public Widget {
public:
    WindowsButton() = default;
    ~WindowsButton() = default;
    void draw() { std::cout << "WindowsButton" << std::endl; }
};

int main() {

    Widget* w = std::unique_ptr(new WindowsButton()).get();
    w->draw();
}

上面的代碼再執行w->draw()的時候會崩潰,why?

首先呢,這麼寫代碼純是吃飽撐的。
智能指針就是幫助我們管理內存的,為何又要賦值給普通指針呢?
好,即使你寫了這樣的代碼,也是對變量生命周期不是很了解:

Widget* w = std::unique_ptr(new WindowsButton()).get();

由於 unique_ptr 擁有對象,所以當unique_ptr 被摧毀的時候,它所指向的對象也會銷毀,所以接下來的w指針指向的是一個已經銷毀的對象,於是調用這個已經銷毀對象的成員函數當然是錯誤的,導致崩潰。

個人覺得,盡量避免使用get方法,既然unique_ptr給我們提供了那麼多的便利條件,我們就不應該铤而走險。

個人還覺得,盡量避免智能指針和普通指針的混合,那樣容易非常的亂,導致內存洩露,導致崩潰。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved