簡體   English   中英

使用智能指針作為類成員

[英]Using smart pointers as a class member

我一直在學習智能指針,最近在課堂上我的助教說我們永遠不要使用原始指針。 現在,我已經做了大量的在線閱讀,並在此網站上研究了不同的問題,但是我仍然對智能指針的某些方面感到困惑。 我的問題是:如果要在程序中使用它,我將使用哪個智能指針? 我將顯示一些代碼。

因此,我有一個基本的Application類,該類從AI類聲明對象。 注意:出於測試原因,我有兩個不同的智能指針,一個是唯一的,一個是共享的。

// Application class in Application.h

class Application
{
public:
    Application(){}
    ~Application(){}

    //... additional non-important variables and such

    unique_ptr<AI> *u_AI; // AI object using a unique pointer
    shared_ptr<AI> *s_AI; // AI object using a shared pointer

    //... additional non-important variables and such

    void init();
    void update();
};

// AI class in AI.h

class AI
{
public:
    AI(){}
    ~AI(){}

    bool isGoingFirst;
};

在應用程序初始化函數中,我想創建AI對象,然后在更新函數中使用它。 我不確定我是否完全正確地聲明了指針,但是我知道它可以編譯並且可以在init函數中分配和打印數據。 下面有更多代碼。

void Application::init()
{
    //.. other initialization's.

    std::shared_ptr<AI> temp(new AI());
    sh_AI = &temp;
    sh_AI->isGoingFirst = true;

    //.. other initialization's.
    // Function ends.
}

void Application::update()
{
    if(sh_AI->get()->isGoingFirst == true)
    {
         // Do something
    }
    else
    {
        // Do something else
    }

    // Other code below
}

在程序的稍后部分,將調用update函數,該函數使用與我在類Application中聲明的AI智能指針相同的函數。 我發現是智能指針AI對象正在被刪除。 我知道智能指針具有自動內存管理功能,但是有沒有一個智能指針可以讓您在不同的功能中使用它,而不會造成任何重大問題,例如內存泄漏或懸掛引用? 還是我錯過了智能指針的全部要點?

很抱歉,如果在另一個問題中回答了這個問題,但我閱讀了許多其他問題,雖然我對智能指針有了更多的了解,但我仍在學習。 謝謝!

正如Neil Kirk在評論中指出的那樣,這些聲明不是您想要的:

unique_ptr<AI> *u_AI; // AI object using a unique pointer
shared_ptr<AI> *s_AI; // AI object using a shared pointer

u_AI和s_AI仍然是原始指針的對象。 重點是消除直接管理原始指針的需要。 所以現在您將它們替換為:

unique_ptr<AI> u_AI; // AI object using a unique pointer
shared_ptr<AI> s_AI; // AI object using a shared pointer

要分配創建的指針,請使用函數make_unique或make_shared:

u_AI = unique_ptr<AI>(new AI()); // Yu may be able to use make_unique like 
                                 // make_shared but it's new to C++14. may not be available
s_AI = make_shared<AI>();

然后,當您需要訪問它們時,您只需假裝它們是指針,因此在更新功能中:

if(sh_AI->get()->isGoingFirst == true)

變成:

if(sh_AI->isGoingFirst == true)

至於何時使用unique_ptr與shared_ptr,您可以通過回答以下問題來回答:有人制作Application副本時我要怎么辦? 即:

Application app1;
app1.init();
Application app2 = app1; // ?? what happens to AI object in app2?

有3種可能的答案:

  1. 我希望app2中有AI的額外副本。 在這種情況下,請使用unique_ptr並確保實現一個執行復制的復制構造函數。
  2. 我希望app2和app1共享AI的副本。 在這種情況下,您使用shared_ptr,默認的副本構造函數將為您完成此工作。
  3. 我不想再有一份Application的副本。 (這對於稱為Application的類來說是有意義的)。 在這種情況下,這並不重要(在這種情況下,我將默認為unique_ptr)並刪除復制構造函數:

    Application(const Application&)=刪除;

簡短答案:由於您的指針是公共的,因此建議您使用shared_ptr 但是,您的指針不必是公共的,因此,如果它是私有的,則可以使用unique_ptr因為您只能在自己的實例中使用它。

事實是,盡管這並沒有多大關系(我知道我會對此表示不滿)。 使用unique_ptr有兩個原因:

  1. 它永遠不會離開您的模塊,您只需要替換裸露的指針
  2. 您想明確表明它不應該離開您的模塊。

另一方面,如果您需要共享指針(即使是只讀方式),則必須使用shared_ptr

很多時候開始使用shared_ptr更為方便,但出於上述原因2),值得使用unique_ptr

不是使用unique_ptr的理由:性能。 我只說了make_shared

現在到您的代碼

這是定義智能指針的方式:

std::shared_ptr<AI> s_AI;
std::unique_ptr<AI> u_AI;

這是您如何初始化它:

s_AI = std::make_shared<AI>(); // or
s_AI = std::shared_ptr<AI>(new AI);

u_AI = std::unique_ptr<AI>(new AI);

請注意,C ++ 11中沒有std :: make_unique。 它將用C ++ 14編寫,編寫替代文件並不難,但事實是在C ++ 11中沒有。

這是使用指針的方式:

s_AI->isGoingFirst;

就是這樣,它的行為就像一個普通的指針。 僅當您必須將其傳遞給需要指針的函數時,才需要使用.get()

這是刪除(空)指針的方法:

s_AI.reset();

同樣,我建議您將指針設為私有。 如果需要將其傳遞出去,請確保使用shared_ptr並編寫一個getter方法:

std::shared_ptr<AI> getAI() const {
    return s_AI;
}

請記住,如果執行此操作,則不能假定當您的Application對象被破壞時,您的AI對象將被破壞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM