Awhile back I threw together something like this in a hurry:
DynamicObject *obj = new DynamicObject();
obj->addProperty (...);
obj->addProperty (...);
obj->addProperty (...);
return JSON::toString (obj);
Generally, whenever I (begrudgingly) call new, the results go immediately into a smart pointer (say ScopedPointer in JUCE). But that isn’t quite right here. DynamicObject is reference counted object. It get’s cast to var by JSON::toString(), and delete will get called by the ref. counting logic. So delete from a smart pointer would be deleting twice. Even in a hurry, I wasn’t a complete idiot, I actually put a comment by the new indicating how the life cycle was being managed. But, once this little throw together left my hands, the lines between new and return grew, and eventually picked up fail logic. Then “return String::empty” caused a leak of a now fairly bloated DynamicObject.
I can think of a number of different ways to get back to a more RAII approach, such as:
var obj (new DynamicObject());
obj.getDynamicObject()->addProperty(...);
...
return JSON::toString (obj);
But they all feel ‘off’ to me. One of the things I admire about Juce is the general legibility of the code. To me, a line like:
ScopedPointer<class> obj = new class();
Is self documenting, new will be matched when the container goes out of scope.
var obj (new DynamicObject());
Not so much. I get it, but it seems to require an explicit comment for the person to follow who, as we can see, may not read the comment…
Sorry, not really a specific question, but I would be interested in hearing different thoughts on how to best manage reference counted objects.