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.
Related
I was asked this in an interview. Seems boost library has something called scoped_pointer. Not sure if he asked about that.
Boost does have a scoped_ptr.
Boost Docs
The primary reason to use scoped_ptr rather than auto_ptr is to let readers of your code know that you intend "resource acquisition is initialization" >to be applied only for the current scope, and have no intent to transfer ownership.
A secondary reason to use scoped_ptr is to prevent a later maintenance programmer from adding a function that transfers ownership by returning the auto_ptr, because the maintenance programmer saw auto_ptr, and assumed ownership could safely be transferred.
Think of bool vs int. We all know that under the covers bool is usually just an int. Indeed, some argued against including bool in the C++ standard because of that. But by coding bool rather than int, you tell your readers what your intent is. Same with scoped_ptr; by using it you are signaling intent.
It has been suggested that scoped_ptr is equivalent to std::auto_ptr const. Ed Brey pointed out, however, that reset will not work on a std::auto_ptr const.
The term most probably referred to the c++ smart-pointers category, which provides scoped owner management for pointers.
The boost documentation page reads
scoped_ptr cannot be used in C++ Standard Library containers. Use shared_ptr if you need a smart pointer that can.
I'm supposing that being non-copyable would be an obstacle for scoped_ptr but since c++11, as far as some containers are concerned, we can :
Constuct in place with emplace_back etc
Move resources without copying
So what's the reason for scoped_ptr being non useable with STL containers ?
The documentation is somewhat out-of-date. Boost.ScopedPtr is an old library, and the maintainers have not cared to keep the documentation in-sync with the latest developments in C++.
In theory a scoped_ptr-like class could work (as evidenced by std::unique_ptr); but in reality, boost::scoped_ptr cannot be usefully used in many standard containers, since it has a private copy constructor and no move constructor. In particular, std::vector and std::deque require that their contents be move-constructible.
scoped_ptr can be used in node-based containers (since such containers do not require that their contents be move-constructible), if only a limited subset of the container's interface is used. Code such as the following is valid:
std::list<boost::scoped_ptr<int>> list;
list.emplace_back(new int(16));
std::map<int, boost::scoped_ptr<int>> map;
map.emplace(
std::piecewise_construct,
std::forward_as_tuple(10),
std::forward_as_tuple(new int(14)));
Even so, it is needlessly painful compared to just using std::unique_ptr (since using std::unique_ptr will allow you to use a far larger proportion of the standard container's interfaces).
As state is the doc,
It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership semantics. Both its name and enforcement of semantics (by being noncopyable) signal its intent to retain ownership solely within the current scope.
and
Q. Why doesn't scoped_ptr have a release() member?
A. When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If scoped_ptr had a release() member, it would become possible to transfer ownership of the held pointer, weakening its role as a way of limiting resource lifetime to a given context.
scope_ptr exists to be safer that the deprecated auto_ptr and to represent RAII.
Now in C++11, we have std::unique_ptr to represent unique ownership.
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.
I am learning about smart pointers (std::auto_ptr) and just read here and here that smart pointers (std::auto_ptr) should not be put in containers (i.e. std::vector) because even most compilers won't complain and it might seem correct. There is no rule that says smart pointers won't be copied internally (by vector class for example) and transfer its ownership, then the pointer will become NULL. In the end, everything will be screwed up.
In reality, how often does this happen?
Sometimes I have vectors of pointers and if in the future I decide I want to have a vector of smart pointers what would my options?
I am aware of C++0x and Boost libraries, but for now, I would prefer to stick to a STL approach.
Yes, you really can't use std::auto_ptr with standard containers. std::auto_ptr copies aren't equivalent, and because standard containers (and algorithms) are allowed to copy their elements at will this screws things up. That is, the operation of copying a std::auto_ptr has a meaning other than a mere copy of an object: it means transferring an ownership.
Your options are:
Use the Boost Smart Pointers library. This is arguably your best option.
Use primitive pointers. This is fast and safe, so long as you manage the pointers properly. At times this can be complex or difficult. For example, you'll have to cope with (avoid) double-delete issues on your own.
Use your own reference-counting smart pointer. That'd be silly; use a Boost Smart Pointer.
The problem you are referring to concerns auto_ptr since it moves ownership on copy. shared_ptr and unique_ptr work just fine with containers.
Any type that you use with a standard container template must conform with the requirements for that container. In particular, the type must satisfy the requirements for CopyConstructible and Assignable types.
Many smart pointers do satisfy these requirements and may be used with standard containers but std::auto_ptr is not one of them because copies of std::auto_ptr are not equivalent to the source that they were created or assigned from.
Although some implementations of standard container may work with auto_ptr in some situations it is dangerous to rely on such implementation details.
theoretically you can use std::auto_ptr with STL containers if you completely understand their internal implementation and don't do anything that can lose auto_ptr ownership, but practically it's much more safe to use containers with raw ptrs.
"In reality, how often does this happen?" - is very dangerous question by itself. first of all, STL - it's not a single standard implementation, there're many. Each one can implement containers in different ways, so your highly tuned code to avoid all "auto_ptr in containers" mines can burst switching to another STL implementation. Also, your code maintenance will be highly complicated, any correctly looking change to your code can break your program. how can you remember that or force others maintainers to remember? putting warnings in any place where such changes can occur? impossible.
so, conclusion: it's just a bad idea that brings nothing but headache
For classes that have an auto ptr data member, I always have a clone method that returns a new auto ptr. I then implement an assignment method and copy constructor that call the clone method (and never the default assignment operator of auto ptr). This way you can safely use the class in STL containers.
Will auto_ptr be deprecated in incoming C++ standard?
Should unique_ptr be used for ownership transfer instead of shared_ptr?
If unique_ptr is not in the standard, then do I need to use shared_ptr instead?
UPDATE: This answer was written in 2010 and as anticipated std::auto_ptr has been deprecated. The advice is entirely valid.
In C++0x std::auto_ptr will be deprecated in favor of std::unique_ptr. The choice of smart pointer will depend on your use case and your requirements, with std::unique_ptr with move semantics for single ownership that can be used inside containers (using move semantics) and std::shared_ptr when ownership is shared.
You should try to use the smart pointer that best fits the situation, choosing the correct pointer type provides other programmers with insight into your design.
Yes, as of today auto_ptr will be deprecated in C++0x and you should use unique_ptr instead. From the latest draft standard (n3035), section D.9
The class template auto_ptr is deprecated. [ Note: The class template unique_ptr (20.9.10) provides a better solution. —end note ]
Until the standard is ratified, it's always possible that the committee will revise this decision although I feel that is unlikely for this decision.
Not only auto_ptr is deprecated in C++11 (D.10, page 1228), it will also be deleted in a future version of C++:
Adopted N4190, and actually removed (not just deprecated) several archaic things from the C++ standard library, including auto_ptr, bind1st/bind2nd, ptr_fun/mem_fun/mem_fun_ref, random_shuffle, and a few more. Those are now all removed from the draft C++17 standard library and will not be part of future portable C++.
Another document about it: Programming Language C++, Library Evolution Working Group - Document N4190, if you want more information.
You can convert any code using auto_ptr automaticaly, by using unique_ptr instead:
Any code using auto_ptr can be mechanically converted to using unique_ptr, with move() inserted whenever auto_ptr was being "copied".
No, it isn't deprecated. It may be, if C++0x ever gets accepted. And it will realistically always be supported. I don't believe that any deprecated feature has ever been dropped from real-world C++ implementations.