Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

initialize a member unique_ptr to empty

In my program, I have a bunch of objects of a custom class Position. The declaration of Position is as follows:

class Position {
public:
    Position(int x, int y);
    ~Position();

    Actor *getActor()           { return actor.get(); };
    void setActor(Actor *actor) { actor = std::move(actor); };
    Actor *clearActor()         { return actor.release(); };

    int getX()  { return x; };
    int getY()  { return y; };

private:
    int x, y;
    std::unique_ptr<Actor> actor;
};

I also have a class called Actor. Not every Position will have an Actor, and so the majority of the time the unique_ptr "actor" of a Position object should be empty (I'm using unique_ptrs to automatically clean up any Actor associated with a Position at runtime).

The Position constructor is as follows:

Position::Position(int x, int y)
{
    this->x = x;
    this->y = y;
    actor.reset(nullptr);
}

However, I know that this isn't correctly setting the stored pointer to nullptr because when I try calling actor.get() inside Position::getActor(), I get an error as follows:

First-chance exception at 0x01096486 in ____.exe: 0xC0000005: Access violation reading location 0x00000008.

Is there a way to initialize a member unique_ptr to nullptr? I know I could get around this by adding a variable to the Actor class that defines whether or not the Actor is active, setting the unique_ptr to a new inactive Actor, and ignoring all inactive Actors, but I'd rather avoid this if possible.

Thanks!

Edit: I've added the code where I call getActor:

bool Grid::addActor(Actor *actor, int x, int y)
{
    Position *destination = at(x, y);

    if (!destination->getActor()) {
        destination->setActor(actor);
        actor->setPosition(x, y);
        actor->setGrid(this);
        return true;
    }
    else {
        inactive_actors.emplace_back(actor);
        return false;
    }
}
like image 236
PreacherJayne Avatar asked Feb 28 '15 03:02

PreacherJayne


People also ask

Can a unique_ptr be null?

Nullability - a scoped_ptr or unique_ptr can be null, a value object can never be. Polymorphism - a value object is always exactly its static type, but you can substitute in different derived types for a unique_ptr. The previously-held object is automatically destroyed when you do this.

Is unique_ptr null after move?

Yes, you can compare it to nullptr after the move and it is guaranteed to compare equal.

What happens when unique_ptr goes out of scope?

std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.


2 Answers

Your error is here:

void setActor(Actor *actor) { actor = std::move(actor); };

You're assigning the result of std::move to the parameter actor. You probably meant to reset the member variable actor with the parameter actor:

void setActor(Actor *actor) { this->actor.reset(actor); };

As a side note, you can simply change your constructor to this:

Position::Position(int x, int y)
: x(x), y(y)
{
}

This will initialize the members x and y with the arguments, and default-initialize std::unique_ptr<Actor> actor to null.

like image 186
emlai Avatar answered Sep 30 '22 16:09

emlai


You don't need to initialize the std::unique pointer to null. Just leave it as its default empty value in the constructor and only ever reset it to point to a non-null pointer.

like image 36
Eamonn O'Brien-Strain Avatar answered Sep 30 '22 18:09

Eamonn O'Brien-Strain