I have a situation where some object has to be passed as an argument of a thread callback function. Object is created dynamically and after it is passed to the thread, object is not needed/used in that context (in a method which starts a thread) any more. Thread function is now the only context which should own the object.
Assuming I want to use some Boost smart pointer (instead of passing to the thread a raw pointer), which one would be the most appropriate here? What is the best practice in this case?
What I actually need is std::auto_ptr with its move semantics through copy constructor. I believe that this smart pointer would perfectly fit here but it is deprecated for well-known reasons (and I cannot rely on tr1 and C++11 pointers; must (and want to) use Boost only as this code is shared between projects that must compile both in Visual Studio 2008 and 2010).
boost::shared_ptr is an option - I could pass it by value but think it would be overkilling. Is there any chance of emulating move semantics (in a safe way) with boost::scoped_ptr? I don't need reference counting here as am not sharing object between two contexts, I just want to transfer the ownership over object from one context to another.
You could use boost::interprocess::unique_ptr, or write your own unique_ptr using Boost.Move.
boost::interprocess::unique_ptr uses Boost.Move in its implementation, and Boost.Move emulates C++11 move semantics C++03.
shared_ptr works well for most situations (including yours). You can use this pattern:
shared_ptr<MyT> param = .....;
thread = boost::thread(thread_routine, param);
param.reset();
... and now only thread_routine holds the object.
Related
As per the document, which says that:
std::unique_ptr is commonly used to manage the lifetime of objects, including:
as the element type in move-aware containers, such as std::vector,
which hold pointers to dynamically-allocated objects (e.g. if
polymorphic behavior is desired) [emphasis mine]
How to understand it in the right way?
Some simple example may helps.
Thanks.
This statement refers to the fact that it was notoriously unsafe to use std::auto_ptr as an element in containers. std::auto_ptr is deprecated already since C++11, but before that there was no move semantics in C++, and auto_ptr was the only "smart" pointer that was really standartized.
std::auto_ptr was similar to std::unique_ptr in that it was destroying the underlying object in the destructor. In contrast to the unique pointer, auto pointer allowed copying: the ownership of the object was transferring to the destination, while the source object was losing the ownership, still pointing to the object. This behavior was unsafe in containers: while you may rely on that the container of auto pointers keeps the ownership, you may easily lose it by simple access to the element (imagine what would happen when you would access the element next time after the actual temporary owner would be destroyed).
It worth mentioning that the STL library provided by Visual Studio C++ 6.0 had a different implementation of auto_ptr: instead of transferring the ownership this "smart" pointer was transferring everything, even the pointer value itself. That meant that the source auto_ptr was becoming empty after the assignment to another "copy" of this pointer. That was safer to store the objects like that in a container, but it caused other problems anyway.
Overall, the problems with usage auto_ptr in containers was [probably] the main reasons why std::auto_ptr was deprecated in C++11.
Returning back to std::unique_ptr: it is safe to use it in containers, and the standard clearly makes an explicit statement referring to the previous problems with std::auto_ptr.
I was reading Top 10 dumb mistakes to avoid with C++11 smart pointer.
Number #5 reads:
Mistake # 5 : Not assigning an object(raw pointer) to a shared_ptr as
soon as it is created !
int main()
{
Aircraft* myAircraft = new Aircraft("F-16");
shared_ptr<aircraft> pAircraft(myAircraft);
...
shared_ptr<aircraft> p2(myAircraft);
// will do a double delete and possibly crash
}
and the recommendation is something like:
Use make_shared or new and immediately construct the pointer with
it.
Ok, no doubt about it the problem and the recommendation.
However I have a question about the design of shared_ptr.
This is a very easy mistake to make and the whole "safe" design of shared_ptr could be thrown away by very easy-to-detect missuses.
Now the question is, could this be easily been fixed with an alternative design of shared_ptr in which the only constructor from raw pointer would be that from a r-value reference?
template<class T>
struct shared_ptr{
shared_ptr(T*&& t){...basically current implementation...}
shared_ptr(T* t) = delete; // this is to...
shared_ptr(T* const& t) = delete; // ... illustrate the point.
shared_ptr(T*& t) = delete;
...
};
In this way shared_ptr could be only initialized from the result of new or some factory function.
Is this an underexploitation of the C++ language in the library?
or What is the point of having a constructor from raw pointer (l-value) reference if this is going to be most likely a misuse?
Is this a historical accident? (e.g. shared_ptr was proposed before r-value references were introduced, etc) Backwards compatibility?
(Of course one could say std::shared_ptr<type>(std::move(ptr)); that that is easier to catch and also a work around if this is really necessary.)
Am I missing something?
Pointers are very easy to copy. Even if you restrict to r-value reference you can sill easily make copies (like when you pass a pointer as a function parameter) which will invalidate the safety setup. Moreover you will run into problems in templates where you can easily have T* const or T*& as a type and you get type mismatches.
So you are proposing to create more restrictions without significant safety gains, which is likely why it was not in the standard to begin with.
The point of make_shared is to atomize the construction of a shared pointer. Say you have f(shared_ptr<int>(new int(5)), throw_some_exception()). The order of parameter invokation is not guaranteed by the standard. The compiler is allowed to create a new int, run throw_some_exception and then construct the shared_ptr which means that you could leak the int (if throw_some_exception actually throws an exception). make_shared just creates the object and the shared pointer inside itself, which doesn't allow the compiler to change the order, so it becomes safe.
I do not have any special insight into the design of shared_ptr, but I think the most likely explanation is that the timelines involved made this impossible:
The shared_ptr was introduced at the same time as rvalue-references, in C++11. The shared_ptr already had a working reference implementation in boost, so it could be expected to be added to standard libraries relatively quickly.
If the constructor for shared_ptr had only supported construction from rvalue references, it would have been unusable until the compiler had also implemented support for rvalue references.
And at that time, compiler and standards development was much more asynchronous, so it could have taken years until all compiler had implemented support, if at all. (export templates were still fresh on peoples minds in 2011)
Additionally, I assume the standards committee would have felt uncomfortable standardizing an API that did not have a reference implementation, and could not even get one until after the standard was published.
There's a number of cases in which you may not be able to call make_shared(). For example, your code may not be responsible for allocating and constructing the class in question. The following paradigm (private constructors + factory functions) is used in some C++ code bases for a variety of reasons:
struct A {
private:
A();
};
A* A_factory();
In this case, if you wanted to stick the A* you get from A_factory() into a shared_ptr<>, you'd have to use the constructor which takes a raw pointer instead of make_shared().
Off the top of my head, some other examples:
You want to get aligned memory for your type using posix_memalign() and then store it in a shared_ptr<> with a custom deleter that calls free() (this use case will go away soon when we add aligned allocation to the language!).
You want to stick a pointer to a memory-mapped region created with mmap() into a shared_ptr<> with a custom deleter that calls munmap() (this use case will go away when we get a standardized facility for shmem, something I'm hoping to work on in the next few months).
You want to stick a pointer allocated by into a shared_ptr<> with a custom deleter.
It is fairly often suggested not to use raw pointers in modern C++, except for a few rare cases. What is the common practice of using smart pointers in C++ library APIs?
The following use cases come up to my mind:
A function which returns a new object.
A function which returns a new object, but it has also created another reference to this object.
A function which only uses an object it receives as an argument.
A function which takes over the ownership of an object.
A function which will store a reference to an object which it has received as an argument, but there might be other references to the very same object (from the callers side).
Unfortunately, a library API design goes far beyond the rule of the language itself: suddenly you have to care about implementations details such as the ABI.
Contrary to C, where common implementations can easily interact together, C++ implementations have very different ABIs (Microsoft ABI for VC++ is completely incompatible with the Itanium ABI used by gcc and Clang), and C++ Standard Library implementations are also incompatible with each others, so that a library compiled with libstdc++ (bundled with gcc) cannot be used by a program using another major version of libstdc++ or another implementation such as libc++ (bundled with Clang) if std:: classes appear in the interface.
Therefore, it really depends on whether you intend your library to be delivered as a binary or assume the user will be in a position to compile the library with its own compiler and Standard Library implementation of choice. Only in the latter case should you expose a C++ interface, for binary distributions sticking to C is better (and it's also easier to integrate with other languages).
With that out of the way, let's assume you decided to use a C++ API:
1) A function which returns a new object.
If the object can be returned by value, do so; if it is polymorphic, use std::unique_ptr<Object>.
2) A function which returns a new object, but it has also created another reference to this object.
Rare Case. I suppose that you mean it has kept a reference, somehow. In this case you have shared ownership so the obvious choice is std::shared_ptr<Object>.
3) A function which only uses an object it receives as an argument.
Much more complex than it first seems, even supposing no reference to the object is kept.
in general, pass by reference (const or not)
unless you intend to operate on a copy of the object, in which case pass by value to benefit from a potential move
4) A function which takes over the ownership of an object.
Simple ownership: std::unique_ptr<Object>.
5) A function which will store a reference to an object which it has received as an argument, but there might be other references to the very same object (from the callers side).
Shared ownership: std::shared_ptr<Object>
Unique pointers may do the job in the general case.
std::unique_ptr<Foo> func();
So that you can assign them directly to auto variables at the callers site, and not worry about memory management.
auto u = func();
In case you need shared ownership, you can convert smart pointers on the callers site:
std::shared_ptr<Foo> s{func()};
However, in case the return type of the function is not polymorphic, and that type is fast to move, you may prefer return by value:
Foo func();
Shared pointers.
std::shared_ptr<Foo> func();
Simply use a reference or const reference to the object, with raw pointers or smart pointers "dereferenced" at the callers site.
void func(Foo& obj);
void func(const Foo& obj);
In case the parameters are optional, you may use raw pointers, so that you can easily pass a nullptr to them.
void func(Foo *obj);
void func(const Foo *obj);
Unique pointers.
void func(std::unique_ptr<Foo> obj);
Const reference to shared pointers.
void func(const std::shared_ptr<Foo>& obj);
The const reference (to shared pointer) is simply an optimization to prevent adjusting the reference count when the function is called and when it returns.
This is a very old question but also an important one.
One school of thought missing from the answers is that you should not return raw nor smart pointers from your API if you can help it.
The raw pointer issue has been discussed. But smart pointers can also be misused, especially in larger projects with complex internal APIs.
A workaround is creating an RAII/wrapper object that holds the ( never-exposed ) smart pointer.
I am trying to create a function that takes an auto_ptr to Base class and I would like to call it with a auto_ptr to Derived class. However I am failing to get it done.
I have tried using it without a reference:
void function(std::auto_ptr<Base> ptr);
std::auto_ptr<Derived> derivedPtr( new ... )
function(derivedPtr); // error: #348: more than one user-defined conversion from
// "std::auto_ptr<Derived>" to "std::auto_ptr<Base>" applies
And with a reference:
void function(std::auto_ptr<Base>& ptr);
std::auto_ptr<Derived> derivedPtr( new ... )
function(derivedPtr); //error: #304: no instance of overloaded function "function"
// matches the argument list
EDIT:
I know auto_ptr is deprecated but I only have access to C++03 and cant access boost. So I would appreciate if the answers would focus on the question itself :) I also do understand the difference of a function taking a reference and a auto_ptr by value. In my actual code the function takes ownership of the auto_ptr so both are fine if I can get the conversion from Derived to Base working.
You are trying to auto_ptr by value and by reference, which are completely different things. The call by value means, you transfer ownership into the function, since auto_ptr does that on copy. Call by reference means there is only auto_ptr outside the function which keeps the ownership.
Since that difference is so very unintuitive, auto_ptr has been deprecated in the standard of 2011 and authors have been discouraging the use of auto_ptr much longer. In short:
Do not use auto_ptr at all.
Use a unique_ptr if you want to transfer ownership into the function, or a reference or plain pointer if you want to leave it outside the function. It depends on the actual case you have.
Update: since you are mentioning that you have to use C++03 without boost, there is a unique_ptr implementaion for C++03: http://howardhinnant.github.io/unique_ptr03.html
It uses a few boost features that can be handwritten easily, so it should be doable to port it to your plaform without having to use boost.
You can cast without ambiguity:
function(static_cast<std::auto_ptr<Base> >(derivedPtr));
Be aware that for this to work, Base must have a virtual destructor. Otherwise the code has undefined behavior.
The reason for the ambiguity is as Arne says in his answer -- it's not obvious to the caller whether function takes a value or a reference, and therefore it's not obvious to the caller whether their auto_ptr will be released or not by making the call, and if it is released whether it's converted to a type that can correctly delete the pointer. The ambiguous conversion AFAIK is there to stop you writing such difficult code. By casting, you make it explicit in the calling code that derivedPtr is released.
It is better to manage memory manually than use auto_ptras its use is so fraught with mistakes.
It is best to use an industrial strength replacememt: at the worst, examine the liberal boost liscense and determine if you can write a clone of your own.
Failimg that, write your own replavement owning_ptr. Create a ownomg_ptr_transfer class template as well. Block copy constructruction on owning_ptr, bit enable implicit conversion from owning_ptr_transfer which takes the underlying poimter. Have a free function or method that moves the underlying pointer to a transfer object.
In essence, if you must, write your own unique_ptr using C++03.
If you will not use someone else's solution, nor will you write your own, then simply mamahe memory manually. auto_ptr is not worth it: it is not just sub optimal compared to unique_ptr, it is actually harmful: its purpose is to make memory management easier, and instead it makes it more error prone. It was an experiment, and it failed.
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.