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.......)
Related
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.
I'm trying to understand the unique_ptr, shared_ptr, and weak_ptr that came in with c++11.
I've heard that weak_ptr's would be nice for things like caching, and breaking cycles, and so on. I've heard that they work well with shared_ptrs.
But in this regard, what's the difference between shared_ptrs and unique_ptrs? Why does weak_ptr only get to be used with one and not the other? Why wouldn't I want to have a weak reference to something owned by someone else?
A weak_ptr is technically a means to hang on to the reference counter of a set of shared_ptrs that manage some shared object. When the last shared_ptr is destroyed the object is destroyed, but its reference counter lives on as long as there are weak_ptrs to it. Thus via any still exising weak_ptr you can check whether the object still exists, or has been destroyed.
If it still exists then from the weak_ptr you can obtain a shared_ptr that lets you reference the object.
The main usage of this is to break cycles.
In particular, an object can contain a weak_ptr holding on to its own reference counter, which allows you to obtain a shared_ptr to the object from the object itself. That is, a shared_ptr that uses the same reference counter as other shared_ptrs to this object. Which is how enable_shared_from_this works.
unique_ptr doesn't have any reference counter, so it doesn't make sense to hang on to that non-existent reference counter.
The major point of a weak pointer is that you can try to make the pointer strong, that is owning:
auto strongPtr = weakPtr.lock();
if (strongPtr)
{
// still existed, now have another reference to the resource
}
else
{
// didn't still exist
}
Note the first path: making a weak pointer stronger requires we take ownership of the object.
This is why it doesn't make sense with unique_ptr: the only way to make the weak pointer strong is to take the resource from somewhere else, and for unique_ptr that would mean leaving that somewhere else with an unexpected null pointer. shared_ptr gets a pass because taking it really means sharing it.
I'm new to C++11 as well, so if someone knows better I would appreciate any corrections.
I think that there wouldn't be much of a reason to, otherwise, you'd use a shared_ptr since it would defeat the whole purpose of a unique_ptr. A unique_ptr has implied semantics that it has complete control over the object to which it points.
class B;
class A
{
public:
A ()
: m_b(new B())
{
}
shared_ptr<B> GimmeB ()
{
return m_b;
}
private:
shared_ptr<B> m_b;
};
Let's say B is a class that semantically should not exist outside of the lifetime of A, i.e., it makes absolutely no sense for B to exist by itself. Should GimmeB return a shared_ptr<B> or a B*?
In general, is it good practice to completely avoid using raw pointers in C++ code, in lieu of smart pointers?
I am of the opinion that shared_ptr should only be used when there is explicit transfer or sharing of ownership, which I think is quite rare outside of cases where a function allocates some memory, populates it with some data, and returns it, and there is understanding between the caller and the callee that the former is now "responsible" for that data.
Your analysis is quite correct, I think. In this situation, I also would return a bare B*, or even a [const] B& if the object is guaranteed to never be null.
Having had some time to peruse smart pointers, I arrived at some guidelines which tell me what to do in many cases:
If you return an object whose lifetime is to be managed by the caller, return std::unique_ptr. The caller can assign it to a std::shared_ptr if it wants.
Returning std::shared_ptr is actually quite rare, and when it makes sense, it is generally obvious: you indicate to the caller that it will prolong the lifetime of the pointed-to object beyond the lifetime of the object which was originally maintaining the resource. Returning shared pointers from factories is no exception: you must do this eg. when you use std::enable_shared_from_this.
You very rarely need std::weak_ptr, except when you want to make sense of the lock method. This has some uses, but they are rare. In your example, if the lifetime of the A object was not deterministic from the caller's point of view, this would have been something to consider.
If you return a reference to an existing object whose lifetime the caller cannot control, then return a bare pointer or a reference. By doing so, you tell the caller that an object exists and that she doesn't have to take care of its lifetime. You should return a reference if you don't make use of the nullptr value.
The question "when should I use shared_ptr and when should I use raw pointers?" has a very simple answer:
Use raw pointers when you do not want to have any ownership attached to the pointer. This job can also often be done with references. Raw pointers can also be used in some low level code (such as for implementing smart pointers, or implementing containers).
Use unique_ptr or scope_ptr when you want unique ownership of the object. This is the most useful option, and should be used in most cases. Unique ownership can also be expressed by simply creating an object directly, rather than using a pointer (this is even better than using a unique_ptr, if it can be done).
Use shared_ptr or intrusive_ptr when you want shared ownership of the pointer. This can be confusing and inefficient, and is often not a good option. Shared ownership can be useful in some complex designs, but should be avoided in general, because it leads to code which is hard to understand.
shared_ptrs perform a totally different task from raw pointers, and neither shared_ptrs nor raw pointers are the best option for the majority of code.
The following is a good rule of thumb:
When there is no transfer of shared ownership references or plain pointers are good enough. (Plain pointers are more flexible than references.)
When there is transfer of ownership but no shared ownership then std::unique_ptr<> is a good choice. Often the case with factory functions.
When there is shared ownership, then it is a good use case for std::shared_ptr<> or boost::intrusive_ptr<>.
It is best to avoid shared ownership, partly because they are most expensive in terms of copying and std::shared_ptr<> takes double of the storage of a plain pointer, but, most importantly, because they are conducive for poor designs where there are no clear owners, which, in turn, leads to a hairball of objects that cannot destroy because they hold shared pointers to each other.
The best design is where clear ownership is established and is hierarchical, so that, ideally, no smart pointers are required at all. For example, if there is a factory that creates unique objects or returns existing ones, it makes sense for the factory to own the objects it creates and just keep them by value in an associative container (such as std::unordered_map), so that it can return plain pointers or references to its users. This factory must have lifetime that starts before its first user and ends after its last user (the hierarchical property), so that users cannot possible have a pointer to an already destroyed object.
If you don't want the callee of GimmeB() to be able to extend the lifetime of the pointer by keeping a copy of the ptr after the instance of A dies, then you definitely should not return a shared_ptr.
If the callee is not supposed to keep the returned pointer for long periods of time, i.e. there's no risk of the instance of A's lifetime expiring before the pointer's, then raw pointer would be better. But even a better choice is simply to use a reference, unless there's a good reason to use an actual raw pointer.
And finally in the case that the returned pointer can exist after the lifetime of the A instance has expired, but you don't want the pointer itself extend the lifetime of the B, then you can return a weak_ptr, which you can use to test whether it still exists.
The bottom line is that there's usually a nicer solution than using a raw pointer.
I agree with your opinion that shared_ptr is best used when explicit sharing of resources occurs, however there are other types of smart pointers available.
In your precise case: why not return a reference ?
A pointer suggests that the data might be null, however here there will always be a B in your A, thus it will never be null. The reference asserts this behavior.
That being said, I have seen people advocating the use of shared_ptr even in non-shared environments, and giving weak_ptr handles, with the idea of "securing" the application and avoiding stale pointers. Unfortunately, since you can recover a shared_ptr from the weak_ptr (and it is the only way to actually manipulate the data), this is still shared ownership even if it was not meant to be.
Note: there is a subtle bug with shared_ptr, a copy of A will share the same B as the original by default, unless you explicitly write a copy constructor and a copy assignment operator. And of course you would not use a raw pointer in A to hold a B, would you :) ?
Of course, another question is whether you actually need to do so. One of the tenets of good design is encapsulation. To achieve encapsulation:
You shall not return handles to your internals (see Law of Demeter).
so perhaps the real answer to your question is that instead of giving away a reference or pointer to B, it should only be modified through A's interface.
Generally, I would avoid using raw pointers as far as possible since they have very ambiguous meaning - you might have to deallocate the pointee, but maybe not, and only human-read and -written documentation tells you what the case is. And documentation is always bad, outdated or misunderstood.
If ownership is an issue, use a smart pointer. If not, I'd use a reference if practicable.
You allocate B at constuction of A.
You say B shouldn't persist outside As lifetime.
Both these point to B being a member of A and a just returning a reference accessor. Are you overengineering this?
I found that the C++ Core Guidelines give some very useful hints for this question:
To use raw pointer(T*) or smarter pointer depends on who owns the object (whose responsibility to release memory of the obj).
own :
smart pointer, owner<T*>
not own:
T*, T&, span<>
owner<>, span<> is defined in Microsoft GSL library
here is the rules of thumb:
1) never use raw pointer(or not own types) to pass ownership
2) smart pointer should only be used when ownership semantics are intended
3) T* or owner designate a individual object(only)
4) use vector/array/span for array
5) To my undetstanding, shared_ptr is usually used when you don't know who will release the obj, for example, one obj is used by multi-thread
It is good practice to avoid using raw pointers, but you can not just replace everything with shared_ptr. In the example, users of your class will assume that it's ok to extend B's lifetime beyond that of A's, and may decide to hold the returned B object for some time for their own reasons. You should return a weak_ptr, or, if B absolutely cannot exist when A is destroyed, a reference to B or simply a raw pointer.
When you say: "Let's say B is a class that semantically should not exist outside of the lifetime of A"
This tells me B should logically not exist without A, but what about physically existing?
If you can be sure no one will try using a *B after A dtors than perhaps a raw pointer will be fine. Otherwise a smarter pointer may be appropriate.
When clients have a direct pointer to A you have to trust they'll handle it appropriately; not try dtoring it etc.
I have a set of objects in a vector of pointers to their baseclass held inside a manager:
std::vector<object*> objectVec;
Classes may wish to spawn one of these objects using the Add() method in the manager. The problem is that they then subsequently need to set or update these objects themselves. I've decided to have Add() return a pointer to the object itself, which is stored in whatever class has decided to spawn one. The problem is dealing with the case where the object behind that pointer may have been deleted.
Add looks like this:
object* ObjectManager::Add(object* obj)
{
objectVec.push_back(obj);
return objectVec.back();
}
and used like this:
objectptr = ObjectManager::OMan()->Add(new object());
Where objectptr is a member of whatever class has called the function. So should that particular object be deleted, the pointer returned by Add would point to rubbish.
Is it my responsibility to ensure that whateverclass::objectptr is always set to NULL if this object is deleted? Or can this be dealt with using some sort of smart pointer? The problem being that I don't need to use a smart pointer to deal with the possibility of a memory leak, but to deal with the case where the stored pointer has become invalid.
Please let me know if i've been unclear, or if the question is badly formed.
Any help would be greatly appreciated.
Yes, you can store smart ptr's instead of raw ptr's in your vector. In this case if somebody releases an object, it's not deleted until the last reference is not released (the one held in vector in your case). You can use boost::shared_ptr or std::shared_ptr (C++11).
If this is not what you want, you can use boost::weak_ptr to store references in your vector. weak_ptr doesn't increment reference counter so if somebody releases an object, it's get deleted, but reference (weak_ptr) stored in your vector allows you to check this.
You likely want weak_ptr and shared_ptr. shared_ptr is a general smart pointer class. weak_ptr is an observer of shared_ptr. When all the references of the shared_ptr go away, instances of weak_ptr "become null" and are easier to deal with than a pointer to a deleted object.
These classes come with Boost.
http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/shared_ptr.htm
http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/weak_ptr.htm
And if I'm not mistaken, there are equivalents built into std namespace on compilers that implement newer C++0x standards. Visual C++ keeps has this built in.
http://blogs.msdn.com/b/vcblog/archive/2011/02/16/10128357.aspx
Oh shoot, looks like everyone else beat me to the answer...
Best is to forget this "manager" idea, but if you do or if you don't, the solution to shared ownership is the same as always, use boost::shared_ptr.
Or, with relatively new compiler, use std::shared_ptr.
Considering that with shared_ptr the ownership issue is taken care of already, then ask yourself, what is it that the "manager" manages?
Cheers & hth.,
Is it my responsibility to ensure that whateverclass::objectptr is always set to NULL if this object is deleted?
You're writing the class, so it's up to you to decide. This is a design decision and either choice is admissible, provided that you document it:
design the application
write the documentation/specification
write the code to matches the specification
Or can this be dealt with using some sort of smart pointer?
Using a smart pointer (strong or weak version) will help achieve whatever behavior you chose for the class. However, it will also strongly affect the client code. In the following code:
class Scene
{
// can't use this object in a call to `ObjectManager::Add()`,
// assuming it uses a smart pointer to deal with object lifetimes.
Object myLight;
};
The use cases for the ObjectManager class should be taken into consideration, on top of simplicity of implementation. Think "write once, use a lot".
Dangling pointers and memory leaks are two different issues, but a proper shared pointer can protect from both. For this particular case, I'd suggest boost::shared_ptr.
Use std::vector<boost::shared_ptr<BaseType>> for the vector type and also have the objects that hold the bare pointers now hold instead a boost::shared_ptr<BaseType>. This will ensure that the pointers will stay valid in the vector and in the objects as long as one of those objects still exist.
If you have differing requirements, you can use a boost::weak_ptr in one of the places holding the pointer (either the vector or the object).
Also, the object can hold a derived type instead of a base type (boost::shared_ptr<DerivedType>) and you can convert between them using boost::shared_static_cast.
Here is the documentation for all of these concepts.
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
pimpl: shared_ptr or unique_ptr
smart pointers (boost) explained
Could someone explain differences between shared_ptr and unique_ptr?
Both of these classes are smart pointers, which means that they automatically (in most cases) will deallocate the object that they point at when that object can no longer be referenced. The difference between the two is how many different pointers of each type can refer to a resource.
When using unique_ptr, there can be at most one unique_ptr pointing at any one resource. When that unique_ptr is destroyed, the resource is automatically reclaimed. Because there can only be one unique_ptr to any resource, any attempt to make a copy of a unique_ptr will cause a compile-time error. For example, this code is illegal:
unique_ptr<T> myPtr(new T); // Okay
unique_ptr<T> myOtherPtr = myPtr; // Error: Can't copy unique_ptr
However, unique_ptr can be moved using the new move semantics:
unique_ptr<T> myPtr(new T); // Okay
unique_ptr<T> myOtherPtr = std::move(myPtr); // Okay, resource now stored in myOtherPtr
Similarly, you can do something like this:
unique_ptr<T> MyFunction() {
unique_ptr<T> myPtr(/* ... */);
/* ... */
return myPtr;
}
This idiom means "I'm returning a managed resource to you. If you don't explicitly capture the return value, then the resource will be cleaned up. If you do, then you now have exclusive ownership of that resource." In this way, you can think of unique_ptr as a safer, better replacement for auto_ptr.
shared_ptr, on the other hand, allows for multiple pointers to point at a given resource. When the very last shared_ptr to a resource is destroyed, the resource will be deallocated. For example, this code is perfectly legal:
shared_ptr<T> myPtr(new T); // Okay
shared_ptr<T> myOtherPtr = myPtr; // Sure! Now have two pointers to the resource.
Internally, shared_ptr uses reference counting to track how many pointers refer to a resource, so you need to be careful not to introduce any reference cycles.
In short:
Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed.
Use shared_ptr when you want multiple pointers to the same resource.
unique_ptr is the light-weight smart pointer of choice if you just have a dynamic object somewhere for which one consumer has sole (hence "unique") responsibility -- maybe a wrapper class that needs to maintain some dynamically allocated object. unique_ptr has very little overhead. It is not copyable, but movable. Its type is template <typename D, typename Deleter> class unique_ptr;, so it depends on two template parameters.
unique_ptr is also what auto_ptr wanted to be in the old C++ but couldn't because of that language's limitations.
shared_ptr on the other hand is a very different animal. The obvious difference is that you can have many consumers sharing responsibility for a dynamic object (hence "shared"), and the object will only be destroyed when all shared pointers have gone away. Additionally you can have observing weak pointers which will intelligently be informed if the shared pointer they're following has disappeared.
Internally, shared_ptr has a lot more going on: There is a reference count, which is updated atomically to allow the use in concurrent code. Also, there's plenty of allocation going on, one for an internal bookkeeping "reference control block", and another (often) for the actual member object.
But there's another big difference: The shared pointers type is always template <typename T> class shared_ptr;, and this is despite the fact that you can initialize it with custom deleters and with custom allocators. The deleter and allocator are tracked using type erasure and virtual function dispatch, which adds to the internal weight of the class, but has the enormous advantage that different sorts of shared pointers of type T are all compatible, no matter the deletion and allocation details. Thus they truly express the concept of "shared responsibility for T" without burdening the consumer with the details!
Both shared_ptr and unique_ptr are designed to be passed by value (with the obvious movability requirement for the unique pointer). Neither should make you worried about the overhead, since their power is truly astounding, but if you have a choice, prefer unique_ptr, and only use shared_ptr if you really need shared responsibility.
unique_ptr
is a smart pointer which owns an object exclusively.
shared_ptr
is a smart pointer for shared ownership. It is both copyable and movable. Multiple smart pointer instances can own the same resource. As soon as the last smart pointer owning the resource goes out of scope, the resource will be freed.
When wrapping a pointer in a unique_ptr you cannot have multiple copies of unique_ptr. The shared_ptr holds a reference counter which count the number of copies of the stored pointer. Each time a shared_ptr is copied, this counter is incremented. Each time a shared_ptr is destructed, this counter is decremented. When this counter reaches 0, then the stored object is destroyed.