Question

I'm in the process of porting some code from Objective C to C++. I'm not as familiar with C++ design patterns as I am with Objective C. In the Cocoa world, there is the very common pattern of writing a factory method that returns an "autoreleased" object. Somethings as simple as:

- (MyClass *)load {

    MyClass* obj = [[MyClass alloc] init];
    return [obj autorelease];
}

This is simple and easy to understand. The method owns the memory it allocates, but can hand it back to the caller, while simultaneously relinquishing ownership. It doesn't have to know or care what the caller does with that memory. If it retains it, the object will survive. If it is completely ignored, the memory will be freed sometime after the current call stack is unwound.

I'm approaching this with some trepidation in C++, because its non ref-counted environment doesn't seem to have anything quite as clean as autorelease, or any kind of ownership policy that is as well defined as those in the Cocoa frameworks. What are the best practices for this kind of pattern in C++?

I'm aware of auto_ptr, but there are also multitudes of concerns with its use, and it seems to have too many shortcomings to be as ubiquitous as autorelease (weird copy semantics, no support for arrays, incompatibility with STL containers, etc).

Boost smart pointers are also an obvious candidate, and some even implement their own reference counting. It seems a little strange to me to have to lean on a 3rd party library for something this mundane though.

Another option that reeks of C would be to just not release the returned memory, but indicate via come commonly adopted naming convention that the caller now owns the returned object. This seems a bit archaic, and is prone to invisible leaks should the caller accidentally ignore the return value.

Was it helpful?

Solution

The "best practices" in the C++03 world (that is, pre-C++11) are one of two things:

  1. Do nothing. This is essentially memory ownership by assumption/convention. If a function returns a pointer, you should know who owns it. Usually, the documentation will tell you. There is no specific syntax for ownership of memory or of transferring ownership.

    This is how an unfortunately large amount of C++ code out there manages memory. It can work, so long as everyone knows what they should be doing and who is responsible for what.

  2. Use some form of smart pointer. std::auto_ptr is odd, but that's about as lightweight as it gets in C++03. No, you can't stick them in standard containers, but it does define a specific pattern of ownership. A boost::shared_ptr is a more effective one, and is more useful in many other places.

C++11 offers std::unique_ptr, which is essentially a "fixed" auto_ptr. It relies on C++11 language features (object movement), so you can't just write one in C++03. You can store them in standard containers and everything. But you can't just pass them around. As the name suggests, they're unique: only one of them can exist which points to that object. When that unique_ptr is destroyed, it deletes the object it references.

You can transfer ownership of a unique_ptr only by giving it away. That is, you cannot share ownership. You can return ownership, which means that the caller now owns it. You can pass ownership to another function, which means that that function owns it. But no two entities can own an object through a unique_ptr.

unique_ptr would be the preferred method of handling a function like this. If the user wants to store it non-uniquely themselves, then they can release it into a std::shared_ptr (which was also adopted into C++11).

OTHER TIPS

I would look at the shared_ptr in boost.

The C++ world is all about libraries. Because no one owns C++ (unlike Objective-C), it grows as the community sees the need.

Well the most c++-like option is using smart pointers..

From what I read, reference counting pointers are your best bet, in the c++11 standard you can use the shared_ptr

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top