When should we inherit from cocos2d::Ref?

Hello guys.

More often than not, we need to create custom classes that have little to relation with other cocos2d classes. I can think of 3 approaches to create and use these custom classes.

First Approach

Don’t inherit from cocos2d::Ref and don’t use new operator. Instead, create the object on stack. No need for memory management as it is automatically handled.

MyCustomObject customObject {2, 3.1416};
customObject.doSomethingAwesome();

Second Approach

Don’t inherit from cocos2d::Ref, but use new operator to create object on heap. Need to call delete to release memory in appropriate place.

auto customObject = new MyCustomObject(2, 3.1416);
customObject->doSomethingAwesome();
...
...
delete customObject;
customObject = nullptr;

Third Approach

Inherit from cocos2d::Ref, use the new operator to create instance and then call autorelease() on the instance to add it to the AutoreleasePool. Possibly write a static create() method to ease instance creation. No need for further memory management as it’s handled by the pool.

class MyCustomObject : public cocos2d::Ref {
public:
    static MyCustomObject* create(int a, float b) {
        auto customObject = new MyCustomObject(a, b);

        if (customObject) {
            customObject->autorelease();
        }
        else {
            delete customObject;
            customObject = nullptr;
        }

        return customObject;
    }
}

I understand that there are pros and cons for each of these approaches, and different approaches are suitable for different cases. Please share which approach you would take for different cases.

Also, is it OK to inherit from cocos2d::Ref just to take advantage of the AutoreleasePool?

Yes it is okay to inherit for autorelease. Ref exists precisely for that reason.

It’s mostly a matter of preference, but Ref can be nice for delegating your custom object’s lifetime management alongside a Scene or other node(s).

My only thought would be to use approach 2 or 3 exclusively for any object that’s more complex than a simple [plain old] data struct. I find it best to not intermix both Ref*-based autorelease with new/delete. It’s fine to do so, but I’ve found people confuse themselves when doing so. Just a suggestion.

2 Likes