简体   繁体   中英

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. 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. 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. 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. What I have found out is that the smart pointer AI object is being deleted. 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:

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. 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:

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 ? ie:

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

There are 3 possible answers:

  1. I want there to be an extra copy of AI in app2. In this case you use unique_ptr and make sure you implement a copy constructor that does the copying.
  2. I want app2 and app1 to share a copy of AI. In this case you use shared_ptr and the default copy constructor will do the job for you.
  3. I don't want there ever to be a copy of Application. (Which makes sense for a class called Application). In this case it doesn't really matter (in which case I would default to unique_ptr) and remove the copy constructor:

    Application(const Application&) = delete;

Short answer: Since your pointer is public, I suggest you use a 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.

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 :

  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 .

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 .

Not a reason to use unique_ptr : performance. All I say is 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. 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.

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() .

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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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