How to use 'this' pointer with smart pointers

I have a static function where I pass a collider and the other collider is itself. I used a regular pointer before and changed it to shared_ptr. I can't find a solution to how I can pass this as a shared pointer. Everytime I do something it seems it deletes itself inside the function.

bool RectCollider::CheckCollision(std::shared_ptr<Collider> other, Vector3& normal, float& depth) {
    
    std::shared_ptr<RectCollider> otherRect = std::dynamic_pointer_cast<RectCollider>(other);
    std::weak_ptr<RectCollider> thisGo = std::shared_ptr<RectCollider>(this);
    if (otherRect) {
        
        if (otherRect == thisGo.lock()) 
            return false;
        return Collision::RectCollision(thisGo.lock(), otherRect, normal, depth);
    }

    std::shared_ptr<CircleCollider> otherCircle = std::dynamic_pointer_cast<CircleCollider>(other);
    if (otherCircle) {
        return Collision::CircleRectCollision(thisGo.lock(), otherCircle, normal, depth);
    }

    return false;
}

I'm sure thisGo is the problem.

I trid to use ChatGPT and it gave me this code and shared_from_this but it doesn't work.

Upvotes: -1

Views: 238

Answers (2)

thank you for helping, I figured out what's wrong myself this how I fixed the script

bool RectCollider::CheckCollision(std::shared_ptr<Collider> other, Vector3& normal, float& depth) {
    
    std::shared_ptr<RectCollider> otherRect = std::dynamic_pointer_cast<RectCollider>(other);
    std::shared_ptr<Collider> sharedThis = shared_from_this();
    if (otherRect) {
        
        if (otherRect == sharedThis) 
            return false;
        return Collision::RectCollision(sharedThis, otherRect, normal, depth);
    }

    std::shared_ptr<CircleCollider> otherCircle = std::dynamic_pointer_cast<CircleCollider>(other);
    if (otherCircle) {
        return Collision::CircleRectCollision(sharedThis, otherCircle, normal, depth);
    }

    return false;
}

Upvotes: 0

Joel
Joel

Reputation: 1678

std::shared_ptr has a reference counter, that is, it tracks how many std::shared_ptr instances point to the same object. Each time a std::shared_ptr goes out of scope, the counter gets decremented. If it reaches 0, then the object pointed to will be deallocated.

Lets look at a simple example:

#include <memory>

class Obj {
public:
    Obj() {
        std::shared_ptr<Obj>(this);
    }
};

int main() {
    Obj o;

    return 0;
}

When constructing our Obj, we create a temporary std::shared_ptr<Obj>. It will get created, the reference counter gets 1, then (since its temporary) it gets destroyed right again and the reference counter gets decremented to 0. This means that the temporary will try to delete our object via the this pointer. But this was not allocated via new and delete-ing memory which was not acquired via new is UB (undefined behavior).

To avoid this deletion you can supply the std::shared_ptr constructor with a custom deleter. This deleter will be called (when the refernce counter reaches 0) instead of a plain delete. If you wrap the this pointer via a std::shared_ptr you probably don't want any deallocation to go on so the deleter can be left empty and you could wrap it in a function like the following:

template <typename T>
std::shared_ptr<T> makeThisShared(T* that) {
    return std::shared_ptr<T>(that, [](T*) {});
}

Upvotes: 0

Related Questions