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:

  • It takes ownership of any non-autoreleased object with a retain count of at least 1.
  • It has value semantics, that is, it is copied by value from stack frame to stack frame, while the “owned” object, as any Objective-C entity, lives happily in the heap.
  • When it goes out of scope, its destructor is called, which sends a “release” message to the owned object.

Here’s how you could use it:

for (NSInteger index = 0; index < 10; ++index)
{
    // A SmartPointer around an NSObject
    SmartPointer obj = SmartPointer::create();
    // 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 array = [*someObj createArrayWithCapacity:5];
    // Here a SmartPointer around an NSNumber
    NSNumber *value = [[NSNumber alloc] initWithInt:1424];
    SmartPointer number = SmartPointer(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.

Similar Posts: