Smart Pointers in Objective-C++

One of the coolest features of C++ are templates, of which I’ve been drooling in the past. One of the most useful things that templates have brought to C++ are smart pointers, which simplify memory management tremendously; they combine the capacity of C++ to instantiate objects in the stack, the flexibility of heap allocation, and template classes, all in one thing.

I’ve talked about them in a previous article in this blog. In C++, a smart pointer will automatically call “delete” on the managed pointer when it goes out of scope, simplifying resource management and providing many more advantages over common pointers, as Andrei Alexandrescu explained in chapter 7 of his book “Modern C++ Design”.

In Objective-C, the “new” and “delete” keywords are replaced by some combination of “alloc / init”, “copy”, “release”, and “autorelease”. But given that Objective-C does not allow for stack allocation of objects (apart from blocks, but that’s another story), I’ve tried to create such a beast in Objective-C++.

These are the features of my smart pointer:

Here’s how you could use it:

for (NSInteger index = 0; index < 10; ++index)
{
    // A SmartPointer around an NSObject
    SmartPointer<NSObject> obj = [[NSObject alloc] init];

    // SomeType is a typedef (see above)
    SomeType someObj = SomeType::create();

    // You can get access to the underlying Objective-C object
    // using "*", ".get()" or "()"; they all return the same pointer.
    // And once you have it, it's a normal Objective-C pointer
    // you can send messages to:
    SmartPointer<NSMutableArray> array = [*someObj createArrayWithCapacity:5];

    // Here a SmartPointer around an NSNumber
    NSNumber *value = [[NSNumber alloc] initWithInt:1424];
    SmartPointer<NSNumber> number = SmartPointer<NSNumber>(value);

    // Playing with the array we got above, just to show it's a normal object
    [array.get() addObject:@"test1"];
    [*array      addObject:@"test2"];
    [*array      addObject:number()];
    [array()     addObject:*obj];

    // After this NSLog call, in the console you should see
    // "[SomeClass dealloc]" which is printed when the SmartPointer goes
    // out of scope, sending the release message on the underlying pointer.
    NSLog(@"array %@", *array);
}

In general, NSAutoreleasePools fit the bill quite comfortably in Objective-C for this kind of tasks, apart from some performance issues in iOS devices (particularly older iPhones and iPod touch devices), but I think there might be cases where just using a “non-autoreleased” approach to resource management might be useful, and typing an extra “[obj release]” line would be too much to ask :)

Of course, this is just an experiment, that I just publish as part of my own curiosity. I would be more than glad to hear some feedback about it from people more knowledgeable in Objective-C and C++ than I am. The code, as usual, is available in Github under a liberal BSD license. Enjoy!

Update, 2011-03-28: just found by pure chance another, much more complete, implementation of this idea (note to self: always Google first!) with its code in Github.