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)
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.
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.
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.
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.
What is the best way to indicate that an object wants to take ownership of another object? So far, I've been using a std::auto_ptr in the public interface, so the client knows that the interface wants to take ownership of the passed object.
However, the latest GCC tells me auto_ptr is deprecated, so I wonder what is recommended? boost::interprocess::unique_pointer looks like a good candidate, but is this really the best solution out there?
boost::interprocess is a library for interprocess communication, so I wouldn't use it for different purposes.
As discussed on this forum:
http://objectmix.com/c/113487-std-auto_ptr-deprecated.html
std::auto_ptr will be declared deprecated in the next version of the standard, where it will be recommended the usage of std::unique_ptr, which requires rvalue references and move semantics to be implemented (that's a fairly complicated feature).
Until the new standard is released, I would simply try to disable the warning if possible, or ignore it, for maximum portability.
If you want to already switch to the next language standard, it is possible since rvalue references have been implemented (see http://russ.yanofsky.org/rref/), so also std::unique_ptr should be supported.
On of the advantages of the new semantics is that you can pass to the move constructor also a temporary or any rvalue; in other cases, this allows avoiding to copy (for instance) objects contained inside a std::vector (during reallocation) before destroying the original ones.
std::unique_ptr is indeed the new recommended way. With C++0x containers will become move-aware, meaning that they can handle types which are movable correctly (i.e., std::vector<std::auto_ptr<x> > does not work, but std::vector<std::unique_ptr<x>> will).
For boost, the boost::interprocess containers already support movable types, where boost::interprocess::unique_ptr is one of them. They resemble movable types in pre C++0x by using some of the "normal" boost-template wizardry, and use r-value references where they are supported.
I didn't know about the auto_ptr dedicated deprecation, though, but I've not followed the new standard evolution closely.
(edit) The implementation of boost::interprocess::unique_ptr is indeed not a "public" smart-pointer like boost::shared_ptr or boost::scoped_ptr, but it is (see boost.interprocess's site) not just for shared-memory, but can also be used for general-purpose.
However, I'm quite sure that if GCC deprecates the auto_ptr template, they already provide their own unique_ptr implementation (not much use to deprecate if you not have a viable alternative yet).
However, that all being said, if you're working on a C++0x platform, use unique_ptr, available from the compiler's lib, if not, stick with auto_ptr.
I agree where possible you should use types where the compiler assists in ownership transfer.
Where you don't have that choice of data types and are passing raw pointers, I follow the Taligent programming guidelines of naming methods which relinquish ownership as orphanBlah and parameters which take ownership as adoptBlah.
std::auto_ptr implements ownership passing on copy and assignment, so there is nothing special you should do about it:
std::auto_ptr< T > p = somePtr; // not p owns object, referenced by somePtr
std::auto_ptr< T > q = myObj.GetAutoPtr(); // not q owns object referenced by auto_ptr in myObj
But passing object ownership is not a good design practice, it conducts to leaks and object lifetime relative errors.
I don't remember std::auto_ptr being deprecated.
Anybody have a link to the appropriate standards meeting where they discuss this?
A quick google found this:
http://objectmix.com/c/113487-std-auto_ptr-deprecated.html
>> In fact the latest publicly available draft lists auto_ptr in appendix
>> D, meaning that there is clear intent to formally deprecate it in the
>> next revision of C++. A new class named unique_ptr is going to provide
>> a replacement for auto_ptr, the main difference being that unique_ptr
>> uses rvalue-references instead of voodoo magic to properly achieve
>> move semantic.
>
> Is a reference implementation available? Is it too early to start using it?
>
In order to use unique_ptr you need first to have a compiler which
properly supports rvalue references. These can be hard to find nowadays,
as the feature has not yet been standardized, although the situation is
quickly improving. For example GCC has very recently added the feature
in v4.3 (http://gcc.gnu.org/gcc-4.3/cxx0x_status.html). If you are lucky
enough to have one of those compilers, most probably they already ship a
version of unique_ptr (it's a sort of benchmark for the feature, you
know). In any case, you can find reference implementations on the
internet by just googling unique_ptr.
So it looks like their are moves to deprecate auto_ptr in favor of unique_ptr (which has the same semantics). But it needs a compiler that supports the proposed new features in the upcoming version of C++.
But there is still another meeting and thus vote to come so things could change before the standard is made concrete.