boost, shared ptr Vs weak ptr? Which to use when? - c++

In my current project I am using boost::shared_ptr quite extensively.
Recently my fellow team mates have also started using weak_ptr. I don't know which one to use and when.
Apart from this, what should I do if I want to convert weak_ptr to shared_ptr. Does putting a lock on weak_ptr to create a shared_ptr affect my code in other thread?

In general and summary,
Strong pointers guarantee their own validity. Use them, for example, when:
You own the object being pointed at; you create it and destroy it
You do not have defined behavior if the object doesn't exist
You need to enforce that the object exists.
Weak pointers guarantee knowing their own validity. Use them, for example, when:
You access it, but it's not yours.
You have defined behavior if the object doesn't exist
Lock() on a weak pointer returns a strong pointer; this is how you access the weak pointer. If the object is no longer valid (it's been deleted, etc), then the strong pointer will be NULL, otherwise, it will point at the object. You will need to check this.
It's set up this way so that you cannot accidentally delete the object while you're using it, because you've made a temporary (local) strong pointer, and thus garunteed the object's existence while that strong pointer remains. When you're done using the object, you generally let the strong pointer fall out of scope (or reassigning it), which then allows the object to be deleted. For multithreading, treat them with same care you treat other things that don't have built-in thread safety, noting that the guarantee I mentioned above will hold when multithreading. AFAIK they don't do anything special past that.
The boost shared pointers also have garbage-collector like features, since when the last strong pointer to an object goes away or points somewhere else, the object gets deleted.
There's also the performance and circular dependencies mentioned in the other answers.
Fundamentally, I would say that the boost shared pointer library allows you to not mess up putting together a program, but it is no substitute for taking the time to properly design your pointers, object ownerships and lifetimes. If you have such a design, you can use the library to enforce it. If you don't have such a design, you're likely to run into different problems than before.

Use weak_ptr when the objects you create contain cyclical references, i.e. shared_ptr to an object with a shared_ptr back to yourself. This is because shared_ptr cannot handle cyclical references - when both objects go out of scope, the mutual referencing means that they are not "garbage collected", so the memory is lost and you have a memory leak. Since weak_ptr does not increase the reference count, the cyclical reference problem does not occur. This also means in general that if you just want to take a pointer to something that is reference counted and do not want to increase its reference count, then use weak_ptr.
Otherwise, you can use shared_ptr.
For more information, check the Boost documentation.

Shared pointers implement reference counting, weak pointers do not affect reference counting and if you don't have shared pointers to an object, only weak pointers, the object gets deleted and the weak pointers now tell you that the object has been lost.
There are two reasons to use a weak pointer:
To eliminate the cost of reference count increase / decrease; however you shouldn't do this because it is error-prone and doesn't really save much time
In bookkeeping data structures, e.g. you have an index of all objects Foo that are "alive", i.e. used somewhere else, and you don't want to keep a Foo alive in the index if all the "real" uses have ended. This is the basic realistic use case for weak pointers. Of course others exist also.
So in general, my recommendation would be to use weak pointers only when you know that you want to let the referenced objects be deleted and want to detect that. In other cases use shared pointers (reference counting), or direct pointers, esp. in method local variables when you know that the objects are not going to get deleted. Also errorprone, though, but faster than shared pointers.
N.B. cyclical objects do not need weak pointers, you can use non-cooked, regular pointers instead in most properly constructed programs. Weak pointers less risky, though.

You should probably not be trying to use weak pointers at all unless you are trying to implement a garbage collector, which is not a hot idea in C++ because it's too hard to keep track of everything that could go wrong closely enough.

Related

Reliably Ensure Memory Safety in C++ 14

I'm converting some old C++ code to use shared_ptr, unique_ptr and weak_ptr, and I keep running into design problems.
I have "generator" methods that return new objects, and accessor methods that return pointers to existing objects. At first glance the solution seems simple; return shared_ptr for new objects, and weak_ptr for accessors.
shared_ptr completely avoids dangling pointers, since if the object is ever deleted all of its shared and weak pointers know about it. But I keep running into cases where I'm not sure if there are cyclic references among my shared pointers. There are many classes and some of them point at each other; is it possible that at some point a cycle formed? The code is sufficiently complex that it's hard to tell - new classes are being created from instructions in a script file. So I don't know if shared_ptr is actually preventing memory leaks and have been manually deleting all objects, which seems to defeat the point.
I considered using unique_ptr instead, since I don't actually need shared ownership anywhere. (The old C++ code certainly didn't have any shared ownership, it's raw pointers only.) But I can't make weak_ptrs from a unique_ptr, so I have to use raw pointers as stand-ins for weak pointers. This solves the memory leak problem, but I can be left with dangling pointers when the unique_ptr is destroyed.
So it seems that I can have one or the other: bulletproof memory leak prevention or bulletproof dangling pointer prevention, but not both.
People have told me I need to keep the entire program structure in my head so I can verify there are no shared pointer cycles, but that seems error prone. My head is, after all, only so big. Is there a way to achieve memory safety while only needing to consider local code?
To me, that is the central tenement of OO programming, and it seems I have lost it in this case.
A strategy that may work for you is to ensure that all the shared pointers in all of your managed objects are const.
Since a const shared_ptr field can only be assigned when it is constructed, this ensures that the objects can only hold shared pointers to objects that were created before they were. (OK, there are ways around that, but you're not going to do it by mistake)
Since "created before" is a total ordering, that ensures that the graph of shared pointers is acyclic.

Is there any advantage to using a naked pointer rather than a weak_ptr?

Question: Are there any compelling reasons to use naked pointers for non-owning resources or should we be using weak_ptr?
CPP.reference states
std::weak_ptr models temporary ownership: when an object needs to be accessed only if it exists, and it may be deleted at any time by someone else
But then, in the accepted answer for Which kind of pointer do I use when? we have the statement:
Use dumb pointers (raw pointers) or references for non-owning references to resources and when you know that the resource will outlive the referencing object / scope. Prefer references and use raw pointers when you need either nullability or resettability.... If you want a non-owning reference to a resource, but you don't know if the resource will outlive the object that references it, pack the resource in a shared_ptr and use a weak_ptr.
This answer is followed by a lot of back-and-forth about the use of naked pointers, with no real resolution. I can't see any reason for using dumb pointers. Am I missing something?
A weak_ptr has a very specific purpose: to break shared_ptr cycles. As an example, std::enable_shared_from_this is based on letting an object contain a weak_ptr to itself. If it directly contained a shared_ptr then that would create a cycle, so instead it has a weak_ptr.
You use a weak_ptr where you would otherwise have had a shared_ptr. The weak_ptr has a higher cost because in addition to the costs of shared_ptr there is the object existence checking that produces a shared_ptr, or not. Also it's a more complex beast so that it's easier to use incorrectly.
I can't think of any way that weak_ptr has anything to do with “temporary ownership” (except that after checking of existence and using a produced shared_ptr, that's one temporary shared ownership, which is repeated again and again for each use). For example, std::enable_shared_from_this has nothing to do with temporary ownership. Ordinarily I would just ignore a source of such a claim, and advice others to ignore it, but cppreference.com is about the best we have in the way of a free online C++ reference. It's odd that it contains a nonsense statement. But, nothing's prefect, as I once remarked to Bjarne in clc++, whereupon he corrected my speling of “prefect”. Hm! Well.
I don't know of any advantage in using a raw pointer rather than a weak_ptr, where a weak_ptr is what's required. A raw pointer can't do a weak_ptr's job of holding on to a shared_ptr's control block, so it seems to me that the mere idea of replacing a weak_ptr with a raw pointer is nonsense. But then, the day one stops being surprised by learning things one could never have thought of, is the day one is dead, and so it may be the case that there is some obscure-to-me such use.
Also, there is no advantage in using a weak_ptr where a raw pointer is what's required. Rather, the weak_ptr introduces a relatively speaking enormous cost, of control block allocation and reference counting. So I can't think of any situation where it would make sense to replace raw pointers with weak_ptr, and I don't expect this to be a case where I learn otherwise.
a weak pointer actually has very little usage. A weak pointer is only useful, if you need it's lock function (transform the pointer into a shared pointer, to prevent garbage collection while you are operating on it). Non owning pointers best, if you just use raw pointer, because of the overhead shared and weak pointer have.

Using smart pointers for observation purposes

i have a large application where task part is modeling objects and the other part is timeline-backed animation of objects. It may be possible that a user deletes an animateable object while the timeline is still animating it.
The timeline accesses (animates) the objects through smart pointers, so it would be perfectly easy to check the object for existence by checking the smart pointer for validity before using it. But this feels a little bit 'dirty' ... like using a safety belt for fixing luggage. But whatever other mechanism we discussed was more or less the same: an object being registered somewhere else and de-registering itself on deletion, exactly what a smart pointer does anyways.
Is this a valid use case for testing smart pointer validity?
In my opinion std::weak_ptr will be good for this job. Weak pointer does not guaratee existence of object under the pointer, if object will be deleted it will be known to other objects referencing for animateable object. Always to use this pointer it has to be locked ( enforcing checking its existence ).
I don't see how you can use std::shared_ptr, here, because it's an Observer Effect problem (by testing something, you're altering it). If you hold an std::shared_ptr to an object, it will be valid by definition.
OTOH, there is std::weak_ptr, which is built exactly for this purpose. It acts as an observer for the shared_ptr only.
std::weak_ptris a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.
If your program is multithreaded, incidentally, you need to handle the case of someone deleting the object while you're observing it, through some other mechanism (e.g., locking).

Pointers, smart pointers or shared pointers? [duplicate]

This question already has answers here:
What is a smart pointer and when should I use one?
(14 answers)
Closed 8 years ago.
I am programming with normal pointers, but I have heard about libraries like Boost that implement smart pointers. I have also seen that in Ogre3D rendering engine there is a deep use of shared pointers.
What exactly is the difference between the three, and should I stick on using just a type of them?
Sydius outlined the types fairly well:
Normal pointers are just that - they point to some thing in memory somewhere. Who owns it? Only the comments will let you know. Who frees it? Hopefully the owner at some point.
Smart pointers are a blanket term that cover many types; I'll assume you meant scoped pointer which uses the RAII pattern. It is a stack-allocated object that wraps a pointer; when it goes out of scope, it calls delete on the pointer it wraps. It "owns" the contained pointer in that it is in charge of deleteing it at some point. They allow you to get a raw reference to the pointer they wrap for passing to other methods, as well as releasing the pointer, allowing someone else to own it. Copying them does not make sense.
Shared pointers is a stack-allocated object that wraps a pointer so that you don't have to know who owns it. When the last shared pointer for an object in memory is destructed, the wrapped pointer will also be deleted.
How about when you should use them? You will either make heavy use of scoped pointers or shared pointers. How many threads are running in your application? If the answer is "potentially a lot", shared pointers can turn out to be a performance bottleneck if used everywhere. The reason being that creating/copying/destructing a shared pointer needs to be an atomic operation, and this can hinder performance if you have many threads running. However, it won't always be the case - only testing will tell you for sure.
There is an argument (that I like) against shared pointers - by using them, you are allowing programmers to ignore who owns a pointer. This can lead to tricky situations with circular references (Java will detect these, but shared pointers cannot) or general programmer laziness in a large code base.
There are two reasons to use scoped pointers. The first is for simple exception safety and cleanup operations - if you want to guarantee that an object is cleaned up no matter what in the face of exceptions, and you don't want to stack allocate that object, put it in a scoped pointer. If the operation is a success, you can feel free to transfer it over to a shared pointer, but in the meantime save the overhead with a scoped pointer.
The other case is when you want clear object ownership. Some teams prefer this, some do not. For instance, a data structure may return pointers to internal objects. Under a scoped pointer, it would return a raw pointer or reference that should be treated as a weak reference - it is an error to access that pointer after the data structure that owns it is destructed, and it is an error to delete it. Under a shared pointer, the owning object can't destruct the internal data it returned if someone still holds a handle on it - this could leave resources open for much longer than necessary, or much worse depending on the code.
the term "smart pointer" includes shared pointers, auto pointers, locking pointers and others. you meant to say auto pointer (more ambiguously known as "owning pointer"), not smart pointer.
Dumb pointers (T*) are never the best solution. They make you do explicit memory management, which is verbose, error prone, and sometimes nigh impossible. But more importantly, they don't signal your intent.
Auto pointers delete the pointee at destruction. For arrays, prefer encapsulations like vector and deque. For other objects, there's very rarely a need to store them on the heap - just use locals and object composition. Still the need for auto pointers arises with functions that return heap pointers -- such as factories and polymorphic returns.
Shared pointers delete the pointee when the last shared pointer to it is destroyed. This is useful when you want a no-brainer, open-ended storage scheme where expected lifetime and ownership can vary widely depending on the situation. Due to the need to keep an (atomic) counter, they're a bit slower than auto pointers. Some say half in jest that shared pointers are for people who can't design systems -- judge for yourself.
For an essential counterpart to shared pointers, look up weak pointers too.
Smart pointers will clean themselves up after they go out of scope (thereby removing fear of most memory leaks). Shared pointers are smart pointers that keep a count of how many instances of the pointer exist, and only clean up the memory when the count reaches zero. In general, only use shared pointers (but be sure to use the correct kind--there is a different one for arrays). They have a lot to do with RAII.
To avoid memory leaks you may use smart pointers whenever you can. There are basically 2 different types of smart pointers in C++
Reference counted (e.g. boost::shared_ptr / std::tr1:shared_ptr)
non reference counted (e.g. boost::scoped_ptr / std::auto_ptr)
The main difference is that reference counted smart pointers can be copied (and used in std:: containers) while scoped_ptr cannot. Non reference counted pointers have almost no overhead or no overhead at all. Reference counting always introduces some kind of overhead.
(I suggest to avoid auto_ptr, it has some serious flaws if used incorrectly)
To add a small bit to Sydius' answer, smart pointers will often provide a more stable solution by catching many easy to make errors. Raw pointers will have some perfromance advantages and can be more flexible in certain circumstances. You may also be forced to use raw pointers when linking into certain 3rd party libraries.

smart pointers + "this" considered harmful?

In a C++ project that uses smart pointers, such as boost::shared_ptr, what is a good design philosophy regarding use of "this"?
Consider that:
It's dangerous to store the raw pointer contained in any smart pointer for later use. You've given up control of object deletion and trust the smart pointer to do it at the right time.
Non-static class members intrinsically use a this pointer. It's a raw pointer and that can't be changed.
If I ever store this in another variable or pass it to another function which could potentially store it for later or bind it in a callback, I'm creating bugs that are introduced when anyone decides to make a shared pointer to my class.
Given that, when is it ever appropriate for me to explicitly use a this pointer? Are there design paradigms that can prevent bugs related to this?
Wrong question
In a C++ project that uses smart pointers
The issue has nothing to do with smart pointers actually. It is only about ownership.
Smart pointers are just tools
They change nothing WRT the concept of ownership, esp. the need to have well-defined ownership in your program, the fact that ownership can be voluntarily transferred, but cannot be taken by a client.
You must understand that smart pointers (also locks and other RAII objects) represent a value and a relationship WRT this value at the same time. A shared_ptr is a reference to an object and establishes a relationship: the object must not be destroyed before this shared_ptr, and when this shared_ptr is destroyed, if it is the last one aliasing this object, the object must be destroyed immediately. (unique_ptr can be viewed as a special case of shared_ptr where there is zero aliasing by definition, so the unique_ptr is always the last one aliasing an object.)
Why you should use smart pointers
It is recommended to use smart pointers because they express a lot with only variables and functions declarations.
Smart pointers can only express a well-defined design, they don't take away the need to define ownership. In contrast, garbage collection takes away the need to define who is responsible for memory deallocation. (But do not take away the need to define who is responsible for other resources clean-up.)
Even in non-purely functional garbage collected languages, you need to make ownership clear: you don't want to overwrite the value of an object if other components still need the old value. This is notably true in Java, where the concept of ownership of mutable data structure is extremely important in threaded programs.
What about raw pointers?
The use of a raw pointer does not mean there is no ownership. It's just not described by a variable declaration. It can be described in comments, in your design documents, etc.
That's why many C++ programmers consider that using raw pointers instead of the adequate smart pointer is inferior: because it's less expressive (I have avoided the terms "good" and "bad" on purpose). I believe the Linux kernel would be more readable with a few C++ objects to express relationships.
You can implement a specific design with or without smart pointers. The implementation that uses smart pointer appropriately will be considered superior by many C++ programmers.
Your real question
In a C++ project, what is a good design philosophy regarding use of "this"?
That's awfully vague.
It's dangerous to store the raw pointer for later use.
Why do you need to a pointer for later use?
You've given up control of object deletion and trust the responsible component to do it at the right time.
Indeed, some component is responsible for the lifetime of the variable. You cannot take the responsibility: it has to be transferred.
If I ever store this in another variable or pass it to another function which could potentially store it for later or bind it in a callback, I'm creating bugs that are introduced when anyone decides to use my class.
Obviously, since the caller is not informed that the function will hide a pointer and use it later without the control of the caller, you are creating bugs.
The solution is obviously to either:
transfer responsibility to handle the lifetime of the object to the function
ensure that the pointer is only saved and used under the control of the caller
Only in the first case, you might end up with a smart pointer in the class implementation.
The source of your problem
I think that your problem is that you are trying hard to complicate matters using smart pointers. Smart pointers are tools to make things easier, not harder. If smart pointers complicate your specification, then rethink your spec in term of simpler things.
Don't try to introduce smart pointers as a solution before you have a problem.
Only introduce smart pointers to solve a specific well-defined problem. Because you don't describe a specific well-defined problem, it is not possible to discuss a specific solution (involving smart pointers or not).
While i don't have a general answer or some idiom, there is boost::enable_shared_from_this . It allows you to get a shared_ptr managing an object that is already managed by shared_ptr. Since in a member function you have no reference to those managing shared_ptr's, enable_shared_ptr does allow you to get a shared_ptr instance and pass that when you need to pass the this pointer.
But this won't solve the issue of passing this from within the constructor, since at that time, no shared_ptr is managing your object yet.
One example of correct use is return *this; in functions like operator++() and operator<<().
When you are using a smart pointer class, you are right that is dangerous to directly expose "this". There are some pointer classes related to boost::shared_ptr<T> that may be of use:
boost::enable_shared_from_this<T>
Provides the ability to have an object return a shared pointer to itself that uses the same reference counting data as an existing shared pointer to the object
boost::weak_ptr<T>
Works hand-in-hand with shared pointers, but do not hold a reference to the object. If all the shared pointers go away and the object is released, a weak pointer will be able to tell that the object no longer exists and will return you NULL instead of a pointer to invalid memory. You can use weak pointers to get shared pointers to a valid reference-counted object.
Neither of these is foolproof, of course, but they'll at least make your code more stable and secure while providing appropriate access and reference counting for your objects.
If you need to use this, just use it explicitly. Smart pointers wrap only pointers of the objects they own - either exclusivelly (unique_ptr) or in a shared manner (shared_ptr).
I personally like to use the this pointer when accessing member variables of the class. For example:
void foo::bar ()
{
this->some_var += 7;
}
It's just a harmless question of style. Some people like it, somepeople don't.
But using the this pointer for any other thing is likely to cause problems. If you really need to do fancy things with it, you should really reconsider your design. I once saw some code that, in the constructor of a class, it assigned the this pointer to another pointer stored somewhere else! That's just crazy, and I can't ever think of a reason to do that. The whole code was a huge mess, by the way.
Can you tell us what exactly do you want to do with the pointer?
Another option is using intrusive smart pointers, and taking care of reference counting within the object itself, not the pointers. This requires a bit more work, but is actually more efficient and easy to control.
Another reason to pass around this is if you want to keep a central registry of all of the objects. In the constructor, an object calls a static method of the registry with this. Its useful for various publish/subscribe mechanisms, or when you don't want the registry to need knowledge of what objects/classes are in the system.