简体   繁体   English

使用智能指针作为类成员

[英]Using smart pointers as a class member

I have been reading up on smart pointers and recently in class my TA said that we should never use raw pointers. 我一直在学习智能指针,最近在课堂上我的助教说我们永远不要使用原始指针。 Now, I've done a lot of reading online and looked at different questions on this website but I'm still confused on some aspects of smart pointers. 现在,我已经做了大量的在线阅读,并在此网站上研究了不同的问题,但是我仍然对智能指针的某些方面感到困惑。 My question is: which smart pointer would I use if I want it to be used across my program? 我的问题是:如果要在程序中使用它,我将使用哪个智能指针? I'll show some code. 我将显示一些代码。

So I have a basic Application class that makes declarations of objects from class AI. 因此,我有一个基本的Application类,该类从AI类声明对象。 Note: I have two different smart pointers, a unique one and a shared one, for testing reasons. 注意:出于测试原因,我有两个不同的智能指针,一个是唯一的,一个是共享的。

// 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;
};

In the Application init function, I want to create the AI object, and then I want to use it in the update function. 在应用程序初始化函数中,我想创建AI对象,然后在更新函数中使用它。 I am not sure if I am declaring my pointer right at all, but I know for a fact that it compiles and it works for assigning and printing out data in the init function. 我不确定我是否完全正确地声明了指针,但是我知道它可以编译并且可以在init函数中分配和打印数据。 More code below. 下面有更多代码。

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
}

Later in my program, the update function is called, which uses the same AI smart pointer that I declared in my class Application. 在程序的稍后部分,将调用update函数,该函数使用与我在类Application中声明的AI智能指针相同的函数。 What I have found out is that the smart pointer AI object is being deleted. 我发现是智能指针AI对象正在被删除。 I understand that smart pointers have automatic memory management, but is there a smart pointer that will allow you to use a it in different functions without creating any major problems, such as memory leaks or dangling references? 我知道智能指针具有自动内存管理功能,但是有没有一个智能指针可以让您在不同的功能中使用它,而不会造成任何重大问题,例如内存泄漏或悬挂引用? Or am I missing the whole point of smart pointers? 还是我错过了智能指针的全部要点?

I'm sorry if this was answered in another question but I read into a lot of the other questions, and while I understand more about smart pointers, I'm still learning. 很抱歉,如果在另一个问题中回答了这个问题,但我阅读了许多其他问题,虽然我对智能指针有了更多的了解,但我仍在学习。 Thank you! 谢谢!

As Neil Kirk pointed out in the comments, these declarations are not what you want: 正如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 and s_AI are still objects to raw pointers. u_AI和s_AI仍然是原始指针的对象。 The whole point is to remove the need to manage the raw pointer directly. 重点是消除直接管理原始指针的需要。 So now you replace them with: 所以现在您将它们替换为:

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

to assign your created pointer, you use the function make_unique or make_shared: 要分配创建的指针,请使用函数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>();

Then, when you need to access them, you just pretend they are pointers, so in your update function: 然后,当您需要访问它们时,您只需假装它们是指针,因此在更新功能中:

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

becomes: 变成:

if(sh_AI->isGoingFirst == true)

As for when to use unique_ptr vs shared_ptr, you answer that by answering the following question: What do I want to happen when someone makes a copy of Application ? 至于何时使用unique_ptr与shared_ptr,您可以通过回答以下问题来回答:有人制作Application副本时我要怎么办? ie: 即:

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

There are 3 possible answers: 有3种可能的答案:

  1. I want there to be an extra copy of AI in app2. 我希望app2中有AI的额外副本。 In this case you use unique_ptr and make sure you implement a copy constructor that does the copying. 在这种情况下,请使用unique_ptr并确保实现一个执行复制的复制构造函数。
  2. I want app2 and app1 to share a copy of AI. 我希望app2和app1共享AI的副本。 In this case you use shared_ptr and the default copy constructor will do the job for you. 在这种情况下,您使用shared_ptr,默认的副本构造函数将为您完成此工作。
  3. I don't want there ever to be a copy of Application. 我不想再有一份Application的副本。 (Which makes sense for a class called Application). (这对于称为Application的类来说是有意义的)。 In this case it doesn't really matter (in which case I would default to unique_ptr) and remove the copy constructor: 在这种情况下,这并不重要(在这种情况下,我将默认为unique_ptr)并删除复制构造函数:

    Application(const Application&) = delete; Application(const Application&)=删除;

Short answer: Since your pointer is public, I suggest you use a shared_ptr . 简短答案:由于您的指针是公共的,因此建议您使用shared_ptr However, your pointer does not need to be public so if it was private you could use a unique_ptr since you only use it in your own instance. 但是,您的指针不必是公共的,因此,如果它是私有的,则可以使用unique_ptr因为您只能在自己的实例中使用它。

The truth is though that it does not really matter much (and I know I'll get some downvotes with this). 事实是,尽管这并没有多大关系(我知道我会对此表示不满)。 There are two reasons to use unique_ptr : 使用unique_ptr有两个原因:

  1. it never leaves your module and you just need a replacement for a naked pointer 它永远不会离开您的模块,您只需要替换裸露的指针
  2. you want to explicitly show that it is not supposed to leave your module. 您想明确表明它不应该离开您的模块。

On the other hand if you need to ever share the pointer (even in a read-only way) then you will have to use a shared_ptr . 另一方面,如果您需要共享指针(即使是只读方式),则必须使用shared_ptr

A lot of times it is more convenient to use shared_ptr to begin with but for reason 2) above it is worth using unique_ptr . 很多时候开始使用shared_ptr更为方便,但出于上述原因2),值得使用unique_ptr

Not a reason to use unique_ptr : performance. 不是使用unique_ptr的理由:性能。 All I say is make_shared . 我只说了make_shared

Now to your code 现在到您的代码

This is how you define a smart pointer: 这是定义智能指针的方式:

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

This is how you initialize it: 这是您如何初始化它:

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

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

Note that there is no std::make_unique in C++11. 请注意,C ++ 11中没有std :: make_unique。 It's going to be in C++14 and it's not that hard to write a replacement but fact is that in C++11 there is none. 它将用C ++ 14编写,编写替代文件并不难,但事实是在C ++ 11中没有。

This is how you use the pointers: 这是使用指针的方式:

s_AI->isGoingFirst;

That's it, it behaves like a normal pointer. 就是这样,它的行为就像一个普通的指针。 Only if you have to pass it to a function that needs a pointer you need to use .get() . 仅当您必须将其传递给需要指针的函数时,才需要使用.get()

here is how you delete (empty) the pointer: 这是删除(空)指针的方法:

s_AI.reset();

Again, I suggest you make your pointer private. 同样,我建议您将指针设为私有。 If you need to pass it out make sure you use a shared_ptr and write a getter method: 如果需要将其传递出去,请确保使用shared_ptr并编写一个getter方法:

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

Remember that if you do this you can't assume that your AI object will be destroyed when your Application object is. 请记住,如果执行此操作,则不能假定当您的Application对象被破坏时,您的AI对象将被破坏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM