Is there some equivalent class for C++1x's std::unique_ptr in the boost libraries? The behavior I'm looking for is being able to have an exception-safe factory function, like so...
std::unique_ptr<Base> create_base()
{
return std::unique_ptr<Base>(new Derived);
}
void some_other_function()
{
std::unique_ptr<Base> b = create_base();
// Do some stuff with b that may or may not throw an exception...
// Now b is destructed automagically.
}
EDIT: Right now, I'm using this hack, which seems like the best I can get at this point...
Base* create_base()
{
return new Derived;
}
void some_other_function()
{
boost::scoped_ptr<Base> b = create_base();
// Do some stuff with b that may or may not throw an exception...
// Now b is deleted automagically.
}
It's not possible to create something like unique_ptr without C++0x (where it's part of the standard library, and so Boost doesn't need to provide it).
Specifically without rvalue references, which are a feature in C++0x, a robust implementation of unique_ptr is impossible, with or without Boost.
In C++03, there are a few possible alternatives, although each have their flaws.
boost::shared_ptr is probably the simplest replacement in terms of capabilites. You can safely use it anywhere you'd otherwise use a unique_ptr and it'd work. It just wouldn't be as efficient, because of the added reference counting. But if you're looking for a simple drop-in replacement that's able to handle everything unique_ptr can do, this is probably your best bet. (Of course, a shared_ptr can do a lot more as well, but it can also simply be used as a drop-in replacement for unique_ptr.)
boost::scoped_ptr is similar to unique_ptr but does not allow transfer of ownership. It works great as long as the smart pointer is meant to retain exclusive ownership throughout its lifetime.
std::auto_ptr works very similar to unique_ptr, but has a few limitations, mainly that it can not be stored in standard library containers. If you're simply looking for a pointer that allows transfer of ownership, but which is not meant to be stored in containers or copied around, this is probably a good bet.
Starting from Boost 1.57 there's an official unique_ptr implementation in Boost.Move library.
From the documentation:
(...) a drop-in replacement for std::unique_ptr, usable also from C++03
compilers.
The code is available in <boost/move/unique_ptr.hpp> header file and lives in boost::movelib namespace. Moreover, Boost.Move library provides make_unique() factory function in <boost/move/make_unique.hpp>, also in boost::movelib namespace.
Hence the example from the question could be implemented this way:
#include <boost/move/unique_ptr.hpp>
using boost::movelib::unique_ptr;
unique_ptr<Base> create_base()
{
return unique_ptr<Base>(new Derived);
}
See a live example on Wandbox. Note that the code compiles fine with gcc 4.6.4 in C++98 mode (!).
What's interesting in boost::movelib::unique_ptr when applied to your case with base/derived classes, the implementation provides a compile-time check for the declaration of a virtual destructor in the base class. If you happen to omit it the code won't compile (click the "Run (...)" button to see the compiler error message).
One minor issue is that includes come from boost/move directory but the code lives in boost::movelib namespace (subtle difference but can be annoying).
See also a thread on boost mailing list for more details.
Thanks to Ion Gaztañaga for this absolutely unique and useful piece of code.
You might want to try Howard Hinnant's 'proof of concept' unique_ptr<> implementation for C++03 (disclaimer - I haven't):
http://howardhinnant.github.io/unique_ptr03.html
One of his examples is returning a unique_ptr<int>:
unique_ptr<int> factory(int i)
{
return unique_ptr<int>(new int(i));
}
How about unique_ptr from the interprocess library?
I've used Howard Hinnant's unique_ptr. If you are not really good at reading crazy metaprogramming errors from you compiler you might want to steer clear. It however does act just like a unique_ptr in 90% of the cases.
Otherwise I'd suggest passing paramters as boost::scoped_ptr& and swap internally to steal ownership. To get unique_ptr style return values use an auto_ptr. Capture the auto_ptr return value in a shared_ptr or scoped_ptr to avoid using the auto_ptr directly.
Related
Occasionally, for fleeting moments, I think auto_ptr is cool. But most of the time I recognize that there are much simpler techniques that make it irrelevant. For example, if I want to have an object freed automatically, even if an exception is thrown, I could new up the object and assign to an auto_ptr. Very cool! But I could have more easily created my object as a local variable, and let the stack take care of it (duh!).
Thus I was not too surprised when I found google C++ coding standards banning the use of auto_ptr. Google states that scoped_ptr should be used instead (if a smart pointer is needed).
I'd like to know if anyone, contrary to my experience, can give a solid reason(s) of when auto_ptr is the best or simplest thing to use. If not, then I suppose I will ban using it myself (following google's lead).
update: For those who expressed concern, no I am not adopting google standards. For example, against google advice, I agree exception-handling should be activated. I also like using preprocessor macros, such as the printable enum I made. It is just the auto_ptr topic that struck me.
update2: It turns out my answer comes from two of the responders below, and a note from Wikipedia. First, Herb Sutter did show a valid use (source-sink idiom and lifetime-linked object composition). Second, there are shops where TR1 and boost are not available or banned and only C++03 is allowed. Third, according to Wikipedia, the C++0x spec is deprecating auto_ptr and replacing it with unique_ptr. So my answer is: use unique_ptr if available to me (on all platforms in consideration) else use auto_ptr for the cases that Sutter depicts.
It's the simplest thing to use when you need a scoped or unique pointer and you are working in a strict C++03 environment with no access to a tr1 implementation or boost.
Herb Sutter can help you out on this one: http://www.drdobbs.com/184403837
While banning auto_ptr seems attractive, but there is one issue:
template <typename T>
some_smart_ptr<T> create();
What will you replace the some_smart_ptr placeholder with ?
The generic answer, shared_ptr, is only worth it if the ownership is truly shared, if the function grants the caller exclusive ownership of the resources, it's misleading at best (and a typical case of premature pessimization as far as I am concerned).
On the other hand, in C++03, no other form of smart pointer can deliver: it's impossible, without move semantics, to provide what we'd like here. auto_ptr or a naked pointer are the two logical contenders. But then a naked pointer exposes you to the risk of leaks if the caller is careless.
With C++0x, unique_ptr advantageously replace auto_ptr in every situation.
std::auto_ptr still has pointer semantics, so automatic (non-pointer) variables aren't a substitute. In particular, std::auto_ptr supports polymorphism and re-assignment. With stack variables you can use references for polymorphism, but references don't allow for re-assignment.
Sometimes std::auto_ptr will do just fine. For example, for implementing a pimpl. True, in the vast majority of cases boost' smart pointer library offers better choices for a smart pointer. But right now std::auto_ptr is a standard solution, whereas boost's smart pointers aren't.
Using auto_ptr as function return value you will enjoy no copiyng overhead and never have memory leak. std::auto_ptr<obj> foo() can be safely called in { foo(); } while obj *foo() cannot. boost::shared_ptr can solve this, but with higher overhead.
Also, some objects can't be created on stack because of memory constraints: thread stacks are relatively small. But boost::scoped_ptr is better in this case since it can't be accidentally released.
Well one reason would be that scoped_ptr is non-copyable, so it's safer to use and harder to make mistakes with. auto_ptr allows transfer of ownership (eg. by passing it another auto_ptr as a constructor parameter). If you need to think things like transferring the ownership, the chances are you're better off with a smart pointer like shared_ptr.
std::auto_ptr lacks const copy constructor, therefore I cannot use it directly in collections. is there some way to have for example vector of std::auto_ptr without using boost pointer collection template?
If you have a C++0x compiler you can use shared_ptr or unique_ptr as appropriate.
There is a good example of correct unique_ptr usage here courtesy of #James McNellis. For a shared_ptr walkthrough look here, courtesy of #D.Shawley. [Upvotes would still be appreciated on those threads, I am sure.]
vector of auto_ptr is always invalid, although Visual C++ v6 disagreed.
No, you just can't have a vector of std::auto_ptr, though there exist many speculations that you can. But if your compiler supports C++0x, you can use std::unique_ptr, which is the new alternative of the deprecated auto pointer which, quote from the new standard, provides a superior alternative. See also this thread
auto_ptr is designed for auto deletion when a variable leaves scope. You don't want to use it in a collection, instead as mentioned above you want to use something like shared_ptr.
Example of auto_ptr's typical use:
void foo()
{
auto_ptr<int> bar = auto_ptr<int>(new int);
...
return; //memory held by auto_ptr is automatically deleted
}
Anything beyond this use is potentially dangerous and/or broken if you are not sure of the special semantics of auto_ptr. (Edit: clarify based on Armen's comment)
With the new standard coming (and parts already available in some compilers), the new type std::unique_ptr is supposed to be a replacement for std::auto_ptr.
Does their usage exactly overlap (so I can do a global find/replace on my code (not that I would do this, but if I did)) or should I be aware of some differences that are not apparent from reading the documentation?
Also if it is a direct replacement, why give it a new name rather than just improve the std::auto_ptr?
You cannot do a global find/replace because you can copy an auto_ptr (with known consequences), but a unique_ptr can only be moved. Anything that looks like
std::auto_ptr<int> p(new int);
std::auto_ptr<int> p2 = p;
will have to become at least like this
std::unique_ptr<int> p(new int);
std::unique_ptr<int> p2 = std::move(p);
As for other differences, unique_ptr can handle arrays correctly (it will call delete[], while auto_ptr will attempt to call delete.
std::auto_ptr and std::unique_ptr are incompatible in someways and a drop in replacement in others. So, no find/replace isn't good enough. However, after a find/replace working through the compile errors should fix everything except weird corner cases. Most of the compile errors will require adding a std::move.
Function scope variable:
100% compatible, as long as you don't pass it by value to another function.
Return type:
not 100% compatible but 99% compatible doesn't seem wrong.
Function parameter by value:
100% compatible with one caveat, unique_ptrs must be passed through a std::move call. This one is simple as the compiler will complain if you don't get it right.
Function parameter by reference:
100% compatible.
Class member variable:
This one is tricky. std::auto_ptrs copy semantics are evil. If the class disallows copying then std::unique_ptr is a drop in replacement. However, if you tried to give the class reasonable copy semantics, you'll need to change the std::auto_ptr handling code. This is simple as the compiler will complain if you don't get it right. If you allowed copying of a class with a std::auto_ptr member without any special code, then shame on you and good luck.
In summary, std::unique_ptr is an unbroken std::auto_ptr. It disallows at compile time behaviors that were often errors when using a std::auto_ptr. So if you used std::auto_ptr with the care it needed, switching to std::unique_ptr should be simple. If you relied on std::auto_ptr's odd behavior, then you need to refactor your code anyway.
AFAIK, unique_ptr is not a direct replacement. The major flaw that it fixes is the implicit transfer of ownership.
std::auto_ptr<int> a(new int(10)), b;
b = a; //implicitly transfers ownership
std::unique_ptr<int> a(new int(10)), b;
b = std::move(a); //ownership must be transferred explicitly
On the other hand, unique_ptr will have completely new capabilities: they can be stored in containers.
Herb Sutter has a nice explanation on GotW #89:
What’s the deal with auto_ptr? auto_ptr is most charitably characterized as a valiant attempt to create a unique_ptr before C++
had move semantics. auto_ptr is now deprecated, and should not be used
in new code.
If you have auto_ptr in an existing code base, when you get a chance
try doing a global search-and-replace of auto_ptr to unique_ptr; the
vast majority of uses will work the same, and it might expose (as a
compile-time error) or fix (silently) a bug or two you didn't know you
had.
In other words, while a global search-and-replace may "break" your code temporarily, you should do it anyway: It may take some time to fix the compile errors, but will save you a lot more trouble in the long run.
We've pretty much moved over to using boost::shared_ptr in all of our code, however we still have some isolated cases where we use std::auto_ptr, including singleton classes:
template < typename TYPE >
class SharedSingleton
{
public:
static TYPE& Instance()
{
if (_ptrInstance.get() == NULL)
_ptrInstance.reset(new TYPE);
return *_ptrInstance;
}
protected:
SharedSingleton() {};
private:
static std::auto_ptr < TYPE > _ptrInstance;
};
I've been told that there's a very good reason why this hasn't been made a shared_ptr, but for the life of me I can't understand why? I know that auto_ptr will eventually get marked as depreciated in the next standard, so I'd like to know what/how I can replace this implementation.
Also, are there any other reasons why you'd consider using an auto_ptr instead of a shared_ptr? And do you see any problems moving to shared_ptr in the future?
Edit:
So in answer to "can I safely replace auto_ptr with shared_ptr in the above code", the answer is yes - however I'll take a small performance hit.
When auto_ptr is eventually marked as depreciated and we move over to std::shared_ptr, we'll need to thoroughly test our code to make sure we're abiding by the different ownership semantics.
auto_ptr and shared_ptr solve entirely different problems. One does not replace the other.
auto_ptr is a thin wrapper around pointers to implement RAII semantics, so that resources are always released, even when facing exceptions. auto_ptr does not perform any reference counting or the like at all, it does not make multiple pointers point to the same object when creating copies. In fact, it's very different. auto_ptr is one of the few classes where the assignment operator modifies the source object. Consider this shameless plug from the auto_ptr wikipedia page:
int *i = new int;
auto_ptr<int> x(i);
auto_ptr<int> y;
y = x;
cout << x.get() << endl; // Print NULL
cout << y.get() << endl; // Print non-NULL address i
Note how executing
y = x;
modifies not only y but also x.
The boost::shared_ptr template makes it easy to handle multiple pointers to the same object, and the object is only deleted after the last reference to it went out of scope. This feature is not useful in your scenario, which (attempts to) implement a Singleton. In your scenario, there's always either 0 references to 1 reference to the only object of the class, if any.
In essence, auto_ptr objects and shared_ptr objects have entirely different semantics (that's why you cannot use the former in containers, but doing so with the latter is fine), and I sure hope you have good tests to catch any regressions you introduced while porting your code. :-}
Others have answered why this code uses an auto_ptr instead of a shared_ptr. To address your other questions:
What/how I can replace this implementation?
Use either boost::scoped_ptr or unique_ptr (available in both Boost and the new C++ standard). Both scoped_ptr and unique_ptr provide strict ownership (and no reference counting overhead), andthey avoid the surprising delete-on-copy semantics of auto_ptr.
Also, are there any other reasons why you'd consider using an auto_ptr instead of a shared_ptr? And do you see any problems moving to shared_ptr in the future?
Personally, I would not use an auto_ptr. Delete-on-copy is just too non-intuitive. Herb Sutter seems to agree. Switching to scoped_ptr, unique_ptr, or shared_ptr should offer no problems. Specifically, shared_ptr should be a drop-in replacement if you don't care about the reference counting overhead. scoped_ptr is a drop-in replacement if you aren't using auto_ptr's transfer-of-ownership capabilities. If you are using transfer-of-ownership, then unique_ptr is almost a drop-in replacement, except that you need to instead explicitly call move to transfer ownership. See here for an example.
auto_ptr is the only kind of smart pointer I use. I use it because I don't use Boost, and because I generally prefer my business/application-oriented classes to explicitly
define deletion semantics and order, rather than depend on
collections of, or individual, smart pointers.
std::auto_ptr is broken in VC++ 8 (which is what we use at work). My main gripe with it is that it allows auto_ptr<T> x = new T();, which of course leads to horrible crashes, while being simple to do by mistake.
From an answer to another question here on stackoverflow:
Note that the implementation of std::auto_ptr in Visual Studio 2005 is horribly broken.
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98871
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101842
I want to use
boost::scoped_ptr, for pointers that shouldn't pass ownership.
boost::shared_ptr, for pointers in containers and elsewhere where they are required.
std::auto_ptr, for pointers that should/can pass ownership.
But since std::auto_ptr is broken for me, I wonder what would be the best approach:
Replace std::auto_ptr with something from the net. Like this this one from Rani Sharoni (haven't tried it yet).
Use boost::shared_ptr instead. Will of course work, although there will be some minor overhead that I don't care about. But I want to use auto_ptr to signal the intent of the pointer. (See this answer for a vote on this approach.)
I will never need to pass ownership in practice, so I shouldn't worry about this.
Update:
Here is what I did:
I copied the aforementioned auto_ptr implementation by Rani Sharoni. From here.
Did some minor tests:
class T
{
public:
T() {
OutputDebugStringA("T\n");
};
~T() {
OutputDebugStringA("~T\n");
};
};
{
fix::auto_ptr<T> x(new T); // This just works.
}
{
fix::auto_ptr<T> x = (new T); // Doesn't compile. Great!
}
{
fix::auto_ptr<T> x = fix::auto_ptr<T>(new T); // Transfer of ownership works also.
}
Of course these tests are by no means exhaustive and you shouldn't trust them. Implementing an exception safe templated class is hairy business. At least this works better than the built in one.
Note: I don't know if I'm allowed to use this implementation yet, with respect to copyright. I have emailed Rani and I'm waiting for a reply. I'll update this post when I know more.
Permission is granted for everyone to use Rani Sharoni's auto_ptr implementation as you wish.
Thank you for all your replies.
Move to boost smart pointers.
In the meantime, you may want to extract a working auto_ptr implementation from an old / another STL, so you have working code.
I believe that auto_ptr semantics are fundamentally broken - it saves typing, but the interface actually is not simpler: you still have to track which instance is the current owner and make sure the owner leaves last.
unique-ptr "fixes" that, by making release not only give up ownership, but also setting the RHS to null. It is the closest replacement for auto-ptr, but with its different semantics it is not a drop-in replacement.
There's an introductory article to boost smart pointers, by, ahem, me.
Have you considered using STLPort?
Use a unique_ptr. I think these were introduced to be a better auto_ptr.
http://www.boost.org/doc/libs/1_35_0/doc/html/interprocess/interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.unique_ptr
In fact, I'm led to believe auto_ptr may be deprecated in favour of it:
http://objectmix.com/c/113487-std-auto_ptr-deprecated.html
Why do you think std::auto_ptr<> is broken.
I would have though that somthing as bad as that would have been reported to the standards comitte!
Do you mean that you need to:
std::auto_ptr<T> x(new T); // Use the explicit constructor.
Use boost::shared_ptr/boost::scoped_ptr. It will be the preferred smart pointer in upcoming C++ standards (is in TR1 already).
Edit:
Please find a related discussion here: Idiomatic use of std::auto_ptr or only use shared_ptr?
As far as I recall, wasn't it :
auto_ptr<T> x = auto_ptr<T>(new T()); ??
Not an answer, but for general interest of anyone for whom these bugs are relevant. There's one more related bug with VC8's auto_ptr, which has to do with implicit upcasts. It's probably the most evil of the bunch, because other bugs just let you compile code that is otherwise illegal according to Standard without failing, but at least compliant code works fine. With this bug, the code that is actually compliant does not work properly.
The problem is this. Standard specifies auto_ptr constructors and conversion operators in such a way that they support implicit upcasting of auto_ptrs, just as with normal pointers. However, VC8 implementation of that does a reinterpret_cast rather than a static_cast there. Naturally, not only this is U.B. by the letter of the standard, but it also breaks with multiple base classes and/or virtual inheritance. Here's an example of legal code broken by this:
struct Base1 { int x; };
struct Base2 { int y; };
struct Derived : Base1, Base2 {};
std::auto_ptr<Derived> createDerived()
{
return std::auto_ptr<Derived>(new Derived);
}
std::auto_ptr<Base2> base2(createDerived());
At one of my past jobs, when we ran into this problem in production, we ended up simply patching the headers ourselves (it's a trivial 2-line fix).