繁体   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