Can I get a raw pointer from boost's weak_ptr? - c++

Is it possible to get a raw pointer from boost::weak_ptr? Boost's shared_ptr has get() method and "->" operator. Is there some rationale behind weak_ptr not having the same functionality?

A weak_ptr holds a non-owning reference, so the object to which it refers may not exist anymore. It would be inherently dangerous to use a raw pointer held by a weak_ptr.
The correct approach is to promote the weak_ptr to a shared_ptr using weak_ptr::lock() and get the pointer from that.
The Boost weak_ptr documentation explains why it would be unsafe to provide get() functionality as part of weak_ptr, and has examples of code that can cause problems.

This is an old question and the accepted answer is good, so I hesitate to post another answer, but one thing that seems missing is a good idiomatic usage example:
boost::weak_ptr<T> weak_example;
...
if (boost::shared_ptr<T> example = weak_example.lock())
{
// do something with example; it's safe to use example.get() to get the
// raw pointer, *only if* it's only used within this scope, not cached.
}
else
{
// do something sensible (often nothing) if the object's already destroyed
}
A key advantage of this idiom is that the strong pointer is scoped to the if-true block, which helps to prevent accidental use of a non-initialised reference, or keeping a strong reference around longer than it is actually required.

You first need to derive the shared_ptr from the weak_ptr before getting hold of the raw pointer.
You can call lock to get the shared_ptr, or the shared_ptr constructor:
boost::weak_ptr<int> example;
...
int* raw = boost::shared_ptr<int>(example).get();

Related

Getting address of object pointed by reference

I'd like to enforce that an object should exist before passing it to a function:
void Class::setStoredObject(MustExist& obj) {
stored_object = &obj;
}
// Lifetime of ptr is my responsibility
std::unique_ptr<MustExist> ptr = std::make_unique<MustExist>();
classObject.setStoredObject(*ptr);
anyway I also need to store that object (big one) by reference or address so I usually grab a pointer to it.
Is this safe to do? I.e. getting the address of a reference to refer to the original pointed-to object.
Alternatively, any other/better way that I could achieve this?
There's nothing wrong with this, per se. Of course, if the original object goes out of scope and gets destroyed, the saved pointer to the object will no longer be valid.
The safest way to ensure that you get an existing object and that it won't be deleted without a possibility to check this, is by instantiating and passing a shared_ptr. This way you can choose to store the shared_ptr so you're sure it won't disappear (but then you need some clean up code) or store as weak_ptr so you can only use it when it still exists.
Storing raw pointers of objects controlled by smart pointers can lead to very subtle issues, that are difficult to trace back to code.
In general, it is not a good design to get and to use a raw pointer out of std::unique_ptr as it breaks all the idea of it.
Dereferencing ptr and passing the object by reference is not a good semantic for what you are trying to do.
If the caller context needs the unique_ptr you should use:
void Class::setStoredObject(std::unique_ptr<MustExist> obj_ptr)
and do the call
classObject.setStoredObject(std::move(ptr));
expressing the fact that the calling context is giving away ownership.
Otherwise you can give up the unique_ptr altogether (its existence is not justified in your example). In this case I would consider either of:
void Class::setStoredObject(const MustExist& obj) // ok for copy
void Class::setStoredObject(MustExist&& obj) // move semantics, expressing the fact that the caller is done using the object.

Why can't a weak_ptr be constructed from a unique_ptr?

If I understand correctly, a weak_ptr doesn't increment the reference count of the managed object, therefore it doesn't represent ownership. It simply lets you access an object, the lifetime of which is managed by someone else.
So I don't really see why a weak_ptr can't be constructed from a unique_ptr, but only a shared_ptr.
Can someone briefly explain this?
If you think about it, a weak_ptr must refer to something other than the object itself. That's because the object can cease to exist (when there are no more strong pointers to it) and the weak_ptr still has to refer to something that contains the information that the object no longer exists.
With a shared_ptr, that something is the thing that contains the reference count. But with a unique_ptr, there is no reference count, so there is no thing that contains the reference count, thus nothing to continue to exist when the object is gone. So there's nothing for a weak_ptr to refer to.
There would also be no sane way to use such a weak_ptr. To use it, you'd have to have some way to guarantee that the object wasn't destroyed while you were using it. That's easy with a shared_ptr -- that's what a shared_ptr does. But how do you do that with a unique_ptr? You obviously can't have two of them, and something else must already own the object or it would have been destroyed since your pointer is weak.
std::weak_ptr can't be used unless you convert it to std::shared_ptr by the means of lock(). if the standard allowed what you suggest, that means that you need to convert std::weak_ptr to unique in order to use it, violating the uniqueness (or re-inventing std::shared_ptr)
In order to illustrate, look at the two pieces of code:
std::shared_ptr<int> shared = std::make_shared<int>(10);
std::weak_ptr<int> weak(shared);
{
*(weak.lock()) = 20; //OK, the temporary shared_ptr will be destroyed but the pointee-integer still has shared to keep it alive
}
Now with your suggestion:
std::unique_ptr<int> unique = std::make_unique<int>(10);
std::weak_ptr<int> weak(unique);
{
*(weak.lock()) = 20; //not OK. the temporary unique_ptr will be destroyed but unique still points at it!
}
That has been said, you may suggest that there is only one unique_ptr, and you still can dereference weak_ptr (without creating another unique_ptr) then there is no problem. But then what is the difference between unique_ptr and shared_ptr with one reference? or moreover, what is the difference between a regular unique_ptr and C-pointers an get by using get?
weak_ptr is not for "general nonowning resources", it has a very specific job - The main goal of weak_ptr is to prevent circular pointing of shared_ptr which will make a memory leak. Anything else needs to be done with plain unique_ptr and shared_ptr.
A shared_ptr basically has two parts:
the pointed-to object
the reference count object
Once the reference count drops to zero the object (#1) is deleted.
The weak_ptr needs to be able to know if the object (#1) still exists. In order to do this, it has to be able to see the reference count object (#2), if it's not zero it can create a shared_ptr for the object (by incrementing the reference count). If the count is zero it will return an empty shared_ptr.
Consider the question of when can the reference count object (#2) be deleted? We must wait until no shared_ptr OR weak_ptr object refer to it. For this purpose the reference count object holds two reference counts, a strong ref and a weak ref. The reference count object will only be deleted when both these counts are zero. This means that part of the memory can only be freed after all the weak references are gone (this implies a hidden disadvantage with make_shared).
tl;dr; weak_ptr depends on a weak reference count which is part of shared_ptr, there cannot be a weak_ptr without a shared_ptr.
Conceptually, there is nothing preventing an implementation where a weak_ptr only provides access and a unique_ptr controls the lifetime. However, there are problems with that:
unique_ptr doesn't use reference counting to begin with. Adding the management structure for managing the weak references would be possible, but require an additional dynamic allocation. Since unique_ptr is supposed to avoid any(!) runtime overhead over a raw pointer, that overhead is not acceptable.
In order to use the object referenced by a weak_ptr, you need to extract a "real" reference from it, which will first validate that the pointer is not expired first and then give you this real reference (a shared_ptr in this case). This means that you suddenly have a second reference to an object that is supposed to be uniquely owned, which is a recipe for errors. This can't be fixed by returning a mixed half-strong pointer that only temporarily delays possible destruction of the pointee, because you could just as well store that one, too, defeating the idea behind unique_ptr.
Just wondering, what problem are you trying to solve using a weak_ptr here?
Looks like everyone is writing here about std::weak_ptr but not about weak poiner concept which I believe is what the author is asking for
I think that no one mentioned why standard library is not providing weak_ptr for unique_ptr. Weak pointer CONCEPT doesn't disclaims unique_ptr usage. Weak pointer is only an information if the object has been already deleted so it's not a magic but very simple generalized observer pattern.
It's because of threadsafety and consistency with shared_ptr.
You just simply can't guarantee that your weak_ptr (created from unique_ptr existing on other thread) will be not destroyed during calling method on pointed object.
It's because weak_ptr needs to be consistent with std::shared_ptr which guarantee threadsafety. You can implement weak_ptr which works correctly with unique_ptr but only on the same thread - lock method will be unnecessary in this case. You can check chromium sources for base::WeakPtr and base::WeakPtrFactory - you can use it freely with unique_ptr.
Chromium weak pointer code is most probably based on last member destruction - you need to add factory as a last member and after that I believe that WeakPtr is informed abut object deleteion (I'm not 100% sure) - so it doesn't looks so hard to implement.
Overall using unique_ptr with weak pointer concept is OK IMHO.
No-one has mentioned the performance aspect of the problem yet, so let me throw my $0.02 in.
weak_ptr must somehow know when the corresponding shared_ptrs have all gone out of scope and the pointed object has been deallocated and destroyed. This means that shared_ptrs need to communicate the destruction towards each weak_ptr to the same object somehow. This has a certain cost – for example, a global hash table needs to be updated, where weak_ptr gets the address from (or nullptr if the object is destroyed).
This also involves locking in a multi-threaded environment, so it can potentially be too slow for some tasks.
However, the goal of unique_ptr is to provide a zero-cost RAII-style abstraction class. Hence, it should not incur any other cost than that of deleteing (or delete[]ing) the dynamically allocated object. The delay imposed by doing a locked or otherwise guarded hash table access, for example, may be comparable to the cost of deallocation, however, which is not desirable in the case of unique_ptr.
It may be useful to distinguish reasons for preferring a unique_ptr over a shared_ptr.
Performance One obvious reason is computational-time and memory use. As currently defined, shared_ptr objects typically need something like a reference-count value, which takes space and also must be actively maintained. unique_ptr objects don't.
Semantics With a unique_ptr, you as the programmer have a pretty good idea when the pointed-to object is going to be destroyed: when the unique_ptr is destroyed or when one of its modifying methods is called. And so on large or unfamiliar code bases, using unique_ptr statically conveys (and enforces) some information about the program's runtime behavior that might not be obvious.
The comments above have generally focused on the performance-based reasons that it would be undesirable for weak_ptr objects to be tied to unique_ptr objects. But one might wonder if the semantics-based argument is sufficient reason for some future version of the STL to support the use-case implied by the original question.
After many years of c++ programing works, i finally realized that the correct way in c++ world is not to use shared_ptr/weak_ptr for ever. We have spent so many time to fix the bugs caused by the unclear ownership of share_ptr.
The solution is to use unque_ptr and some weak pointer for unique_ptr instead, just as what's expected in this topic.
cpp standard library has no weak pointer for unique_ptr, so i create a very simple, but useful libary here --
https://github.com/xhawk18/noshared_ptr
It has two new smart pointers,
noshared_ptr<T>, a new kind of unique_ptr
noweak_ptr<T>, the weak pointer for noshare_ptr<T>
I demonstrated the problem to myself with a MWE implementing weak_ptr on single objects. (I implement it on X here, but X can be anything that can tell us when it dies, such as a unique_ptr with a custom deleter).
The ultimate problem however is that at some point we need reference counting on the weak pointers themselves, because while X is not shared, the weak pointers are shared. This takes us full circle back to using shared_ptr again.
Perhaps the only advantage of doing this is that the intent of single ownership is clearer and cannot be violated, however, as Stroustrup suggests and is quoted this answer, this can be hinted at with the using statement.
#include <iostream>
#include <memory>
template<typename T>
struct ControlBlock
{
T* Target;
explicit ControlBlock(T* target) : Target(target) {}
};
template<typename T>
struct WeakReference
{
std::shared_ptr<ControlBlock<T>> ControlBlock;
T* Get() { return ControlBlock ? ControlBlock->Target : nullptr; }
};
template<typename T>
struct WeakReferenceRoot
{
WeakReference<T> _weakRef;
WeakReferenceRoot(T* target) : _weakRef{std::make_shared<ControlBlock<T>>(target)} { }
const WeakReference<T>& GetReference() { return _weakRef; }
~WeakReferenceRoot() { _weakRef.ControlBlock->Target = nullptr; }
};
struct Customer
{
WeakReferenceRoot<Customer> Weak{this};
};
int main() {
WeakReference<Customer> someRef;
std::cout << "BEFORE SCOPE - WEAK REFERENCE IS " << someRef.Get() << "\n";
{
Customer obj{};
someRef = obj.Weak.GetReference();
std::cout << "IN SCOPE - WEAK REFERENCE IS " << someRef.Get() << "\n";
}
std::cout << "OUT OF SCOPE - WEAK REFERENCE IS " << someRef.Get() << "\n";
return 0;
}
Sadly as with many cases - cause the C++ committee just didn't care and dismissed such usecases.
How it is:
weak_ptr was specified in terms of shared-pointer, precluding any attempts at making it a more broadly useful smart-pointer. In C++ conceptually a weak-ptr is a non-owning pointer that MUST be converted to a shared_ptr to access the underlying object. And as a unique_ptr does not support any sort of reference-counting (as it is the unique owner by definition) converting a weak_ptr to a pointer with any sort of ownership is not allowed.
It is sadly a bit too late to get good well-named smart-pointers that offer a bit more generality.
But you can create something like that:
To make it safe you would need your own deleter (unique_ptr has the deleter in the type), and a new non-owning unique_ptr_observer that changes the deleter. When creating an observer it would register a cleanup-handler as the deleter. That way you can have a unique_ptr_observer that can check if the Threadsafety would still be a problem as you would need either a locking-mechanism, create copies for readout, or some other way to prevent the pointer from getting deleted while you are actively looking at it.
(it is so annoying that the deleter is part of the type.......)

How to enforce non-ownership of a pointer?

I have a method which creates an object in an auto_ptr, sticks that auto_ptr into a vector, and then returns a raw pointer to the object for convenience.
The problem with this design is that it returns a raw pointer. It's really easy for the caller to misunderstand that this pointer is non-owned and wrap the result of this call into a managed pointer, which causes a memory access violation when that memory gets double free'd.
int main (void)
{
{
std::auto_ptr<int> foo = ThisMethodReturnsNonOwningPtr(); // Uhoh
}
ThisMethodUsesThePtr(); // Crash
return 0;
}
Ideally, I would like to return something like a pointer which can not be converted to a managed pointer so I don't have to worry about the caller doing this.
Alternatively, I might just return an index into the array, but it's real convenient just being able to pass the pointer around, and who knows maybe I will end up shuffling or sorting the array later.
First, if you can stick an auto_ptr into a vector, it's time to
upgrade your compiler or your library. This hasn't been legal
since the first standard in 1998. If you've got C++11, you can
use std::unique_ptr; if not, you'll need to keep raw pointers
in the vector. In both cases, you'll want to wrap the vector:
with std::unique_ptr, so that the client doesn't have to do
anything fancy to get the actual pointer, and with raw pointers,
so that you can manage the memory associated with them.
For the rest, just return a raw pointer. If you have
programmers that go around deleting random pointers, you're sunk
anyway; most of the time, raw pointers are for navigation, and
are just as likely to point to an object with static lifetime as
to anything else.
Stop using auto_ptr and start using unique_ptr or shared_ptr. The latter has reference counting so you can safely return the object and others can use it. The data it points to will not be freed until all references are released.
there is no other alternative if you need to safely return a pointer to the object and still be able to alter the vector. You could use a unique_ptr to prevent a caller from treating the returned pointer as if it owned it.
Last resort is to slap comments on the code to say that the vector owns the object and the pointer is only to be used as a convenience. Its not as good as getting the compiler to check calling code, but it can be the only way if you restrict your options as you mentioned.
Create a wrapper class template raw_ptr<T> which encapsulates a T*.
If you now implement operator* and operator-> but no conversion operator, you can no longer assign this pointer to another smart pointer, because that assignment would require two custom conversions (raw_ptr<T> → T* → smart_ptr<T>), which is not allowed in C++.
Notice that, as others have said, you should not use auto_ptr<T> – it’s deprecated for good reasons. Use std::unique_ptr<T> instead. For one thing, you cannot actually safely stick auto_ptrs into a std::vector, great care has to be taken to not accidentally copy (and thus invalidate) such pointers.
I'm always reluctant to write answers that depend on boost since not everyone is able to use it and it's almost always overkill to pull it in for just one little thing, but if you have it anyway, you could return a boost::optional<&>. On the surface it doesn't seem an optional reference could work, but it (mostly) does. See boost's documentation.
This would give you the nullability you require (return boost::none to indicate an error) while making it very clear that the caller is not to take ownership of the object.
If you don't want the object to be deleted in conventional means using delete operator, you could make the destructor of the class private and implement destroy() function which self-destructs the object.
Better would be if you could make the function return something like shared_ptr.
A third option could be just to have a class something like template<typename> struct non_ownership_ptr; which the function returns instead of a raw pointer. This pointer class just holds the pointer and you would have to explicitly use auto_ptr<T> p=foo().non_owned_ptr; to avoid (or at least reduce) accidental assignment to auto_ptr or such.

Raw pointer management

Is it appropriate for a class to return a a raw pointer in a "create" method and take a raw pointer argument in its "destroy" method? The aforementioned class stores the pointer in a container and finds/deletes the specified object through the destroy method.
Or should I be using smart pointers? If I understand correctly, smart pointers indicate ownership, but the class is solely responsible for both creation and destruction of the object.
The question is: Can you programatically describe the acquire/release behaviour that the code should have? If yes, i.e. the behaviour isn't a series of unique events without any pattern, then you can write a handle class that implements this behaviour. Even more, this handle class will be able to guarantee the behaviour, which is what smart pointers are all about. It's not just about correctness of code, but about extended guarantees that make it easier to write correct code.
Also, smart pointers don't always indicate ownership, though they do in most cases. There is also a distinction between shared ownership (shared_ptr) and exclusive ownership (auto_ptr, unique_ptr). Then, there is e.g. a mere reference without ownership (weak_ptr).
To me, it sounds like you might want to return a shared_ptr with an according deleter. The factory can then e.g. keep a weak_ptr to retain some access to the according objects, while the shared_ptr guarantees correct cleanup. Make sure you regularly purge expired weak_ptrs from the factories internals though.
In no case would I return a raw pointer. The question this bears is: What should the caller do with it when they are done? Call delete? Call some specific destroy() function? Both of these are better handled by a smart pointer. Also, if the factory retains ownership and reserves itself the right to discard the object at any time, how is the one holding a raw pointer informed about the fact that this pointer will become invalid? A simple answer would be to use a smart pointer that gets notified, like e.g. weak_ptr.

best practice when returning smart pointers

What is the best practice when returning a smart pointer, for example a boost::shared_ptr? Should I by standard return the smart pointer, or the underlying raw pointer? I come from C# so I tend to always return smart pointers, because it feels right. Like this (skipping const-correctness for shorter code):
class X
{
public:
boost::shared_ptr<Y> getInternal() {return m_internal;}
private:
boost::shared_ptr<Y> m_internal;
}
However I've seen some experienced coders returning the raw pointer, and putting the raw pointers in vectors. What is the right way to do it?
There is no "right" way. It really depends on the context.
You can internally handle memory with a smart pointer and externally give references or raw pointers. After all, the user of your interface doesn't need to know how you manage memory internally. In a synchronous context this is safe and efficient. In an asynchronous context, there are many pitfalls.
If you're unsure about what to do you can safely return smart pointers to your caller. The object will be deallocated when the references count reaches zero. Just make sure that you don't have a class that keeps smart pointers of objects for ever thus preventing the deallocation when needed.
As a last note, in C++ don't overuse dynamically allocated objects. There are many cases where you don't need a pointer and can work on references and const references. That's safer and reduces the pressure on the memory allocator.
It depends on what the meaning of the pointer is.
When returning a shared_pointer, you are syntactically saying "You will share ownership of this object", such that, if the the original container object dies before you release your pointer, that object will still exist.
Returning a raw pointer says: "You know about this object, but don't own it". It's a way of passing control, but not keeping the lifetime tied to the original owner.
(in some older c-programs, it means "It's now your problem to delete me", but I'd heavily recommend avoiding this one)
Typically, defaulting to shared saves me a lot of hassle, but it depends on your design.
I follow the following guidelines for passing pointers arguments to functions and returning pointers:
boost::shared_ptr
API and client are sharing ownership of this object. However you have to be careful to avoid circular references with shared_ptr, if the objects represent some kind of graph. I try to limit my use of shared_ptr for this reason.
boost::weak_ptr / raw pointer
API owns this object, you are allowed share it while it is valid. If there is a chance the client will live longer than the api I use a weak_ptr.
std::auto_ptr
API is creating an object but the client owns the object. This ensures that the returning code is exception safe, and clearly states that ownership is being transferred.
boost::scoped_ptr
For pointers to objects stored on the stack or as class member variables. I try to use scoped_ptr first.
Like all guidelines there will be times when the rules conflict or have to be bent, then I try to use intelligence.
I typically return "owning"/"unique" smart pointers from factories or similar to make it clear who is responsible for cleaning up.
This example https://ideone.com/qJnzva shows how to return a std::unique_ptr that will be deleted when the scope of the variable that the caller assigns the value to goes out of scope.
While it's true that the smart pointer deletes its own pointer, the lifetime of the variable holding the smart pointer is 100% controlled by the caller, so the caller decides when the pointer is deleted. However, since it's a "unique" and "owning" smart pointer, no other client can control the lifetime.
I would never return a raw pointer, instead I would return a weak_ptr to tell the user of the pointer that he doesn't have the control over the resource.
If you return a weak_ptr its very unlikely that there will be dangling pointers in the application.
If there is a performance problem I would return a reference to the object and a hasValidXObject method.
In my opinion, in C++, you should always have to justify the use of an unguarded pointer.
There could be many valid reasons: a need for very high performance, for very low memory usage, for dealing with legacy libraries, because of some issue with the underlying data structure the pointer is storing. But [dynamically allocated] pointers are somewhat 'evil', in that you have to deallocate the memory at every possible execution path and you will almost certainly forget one.
I wouldn't put raw pointers in vectors.
In case they use auto_ptr or boost::scoped_ptr, they can't use (or return) anything but raw pointers. That could explain their way of coding, i guess.
depends on your goals.
blindly returning smart ptr to internal data might not be a good idea (which is very sensitive to the task you're trying to solve) - you might be better off just offering some doX() and doY() that use the pointer internally instead.
on the other hand, if returning the smart ptr, you should also consider that you'll create no mutual circular references when objects end up unable to destroy each other (weak_ptr might be a better option in that case).
otherwise, like already mentioned above, performance/legacy code/lifetime considerations should all be taken into account.
const boost::shared_ptr &getInternal() {return m_internal;}
This avoids a copy.
Sometimes you'll like to return a reference, for example:
Y &operator*() { return *m_internal; }
const Y &operator*() const { return *m_internal; }
This is good too only if the reference will be used and discarded inmediately.
The same goes for a raw pointer.
Returning a weak_ptr is also an option.
The 4 are good depending on the goals. This question requires a more extensive discussion.