Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Referring to "this" as a shared_ptr? [duplicate]

I'm learning about c++11 features, specifically shared_ptr, and I am having an issue with referring to this and using it as a reference for other classes.

The reason for doing this is I have a Simulation instance that is passed around to other instances within the simulation (e.g. Apple) so they can themselves modify the simulation, or even remove themselves from the simulation.

In my more complex code I get a double free error (when the program exists) which as I understand from here that I should not create a shared_ptr twice on the same raw object. How do I pass this to the Apple object as a shared_ptr when the Simulation class doesn't know that this is already a shared_ptr?

My thought is to pass the shared_ptr in the initialisation argument but that seems redundant, e.g.:

// The argument is a std::shared_ptr<Simulation>
simulation->initSomethingElse(simulation);

Maybe I am trying to implement this in an unusual pattern, or maybe my understanding is not quite right? Maybe there is a nicer way of doing this instead?

I have a simplified example below:

#include <memory>

class Simulation;

class Apple {
public:
    void init(std::shared_ptr<Simulation> simulation) {
        this->simulation = simulation;
    };

private:
    std::shared_ptr<Simulation> simulation;

};


class Simulation {
public:
    void initSomethingElse() {
        auto apple = std::shared_ptr<Apple>(new Apple());

        // incorrect second reference to the raw pointer
        apple->init(std::shared_ptr<Simulation>(this));
    };
};


int main() {

    auto simulation = std::shared_ptr<Simulation>(new Simulation());
    simulation->initSomethingElse();

    return 0;
}
like image 813
gak Avatar asked Sep 25 '14 04:09

gak


2 Answers

The first thing that comes to mind is to use enable_shared_from_this: http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

But the second thing that comes to mind is that the Simulation should be managing the lifetime of the Apple, so the Apple need not manage the lifetime of the Simulation. Therefore, you are better off having the Apple not hold a shared_ptr<Simulation> - only main() or some high-level function should manage the lifetime of the Simulation.

If you aren't careful you will end up with cyclic references. Don't assume every pointer in C++11 should be a shared_ptr.

like image 135
John Zwinck Avatar answered Nov 01 '22 19:11

John Zwinck


Use enable_shared_from_this so a function on the object can create a new shared_ptr to itself. You'll want to do this instead of the apple->init(std::shared_ptr<Simulation>(this)); line that creates a second shared_ptr to the Simulation. You'll also want to rturn or save the apple shared_ptr somewhere, as at present the Apple only exists while initSomethingElse() is running, which doesn't seem very useful...?

like image 35
Tony Delroy Avatar answered Nov 01 '22 19:11

Tony Delroy