I have a GUI to interact with the user, but I have an OOP design problem with this.
Through a dialog the user specifies CDiscreteDistributions and they are stored in a std::vector<CDiscreteDistribution*> in the MyAppDoc class for serialization. Through another dialog the user chooses a type of CDistribution for a particular CParameter. CDiscreteDistribution, CConstantDistribution, and CContinuousDistribution inherit CDistribution, and CParameter has a polymorphic pointer to a CDistribution member variable. MyAppDoc has a container class of CParameter. Thus the CDiscreteDistributions are pointed two twice, but only exist once.
In summary, MyAppDoc has
std::vector<CDiscreteDistribution*>
CContainer which has many CParameter which have
CDistribution* which can point to one of
CDiscreteDistribution which is one of the CDiscreteDistribution*s stored above
CConstantDistribution created/destroyed by CParameter
CContinuousDistribution created/destroyed by CParameter
This design pattern is causing me various nightmares in porting the app to use shared_ptr due to double deletes and serialization (boost). Should one of the pointers to CDiscreteDistribution be a weak_ptr? If so where should own the pointer?
Thanks for any help!
EDIT:
I re-thought the reasoning for having std::vector<CDiscreteDistribution*> and it was just to avoid copying the vector into and out of the GUI. But the objects are quite small, and so I've broken the link between them and suffer the minor performance implications. Now MyAppDoc has:
std::vector<CDiscreteDistribution>
CContainer which has many CParameter which have
CDistribution* which can point to one of
CDiscreteDistribution created/destroyed by CParameter, copied from one of the CDiscreteDistributions stored above
CConstantDistribution created/destroyed by CParameter
CContinuousDistribution created/destroyed by CParameter
I think part of the problem was boost::serialization made two shared_ptrs for each CDiscreteDistribution that weren't aware of each other's existence. Now the only issue is backwards compatibility to files created with the previous versions.
I figure this 'solution' is actually just avoiding a proper design!
The question is described not enough to understand the full situation, complications and exact problem, but in general -
I assume you want to use shared_ptr to not have to manually delete() objects
If so, see if you can solve it by not using shared_ptr, but rather using boost::ptr_vector instead of a vector of raw pointers; the ptr_vector will then handle memory management for you.
I'm not even sure what the shared_ptr would bring you - it's quite obvious, I'd say from my limited understanding of the situation, that the Doc owns the CDiscreteDistribution objects. Whoever owns the other two types of Distributions is responsible for deleting them; this can be done though a shared_ptr or otherwise. (you say 'locally instanced' but that doesn't mean much - are they instantiated on the heap or the stack? What is their lifetime? Why is their lifetime different from the DiscreteDistribution objects? What is 'local' - local to what?)
I agree with Roel that the question is not fully specified. But having done several extensive conversions from raw pointers to shared_ptr, I can give you a little advice.
weak_ptr should not be necessary unless you have circular dependencies. In other words, if an object A has a shared_ptr to object B and object B has a shared_ptr back to object A. In this case, it's impossible for the reference count of either pointer to go to 0, so you would either need to manually intervene to break the cycle, or use weak_ptr to designate one side as dependent.
I'm confused why you have issues with double deletion when using shared_ptr. One of the advantages of smart pointers in general is that you don't have to actually delete them. If you've converted all your raw pointers to shared_ptr, you shouldn't have this problem. If your CConstantDistribution and CContinuousDistribution objects are actually locals rather than allocated with new (I can't tell 100% if this is the case from your description), you can make them shared_ptr objects that are initialized in your constructor, if you can change the app's code. This would allow you to make your std::vector<CDiscreteDistribution*> a container of shared_ptr to CDiscreteDistribution instead. At that point, you shouldn't have to worry about deleting those objects at all, unless you have circular references as described above. Even if you do, you'd have converted a double-delete crash to a memory leak, which is generally less bad.
Serialization can be tough. Since you've tagged the question with MFC, I'll assume you're using MFC serialization. I generally don't have problems when wrapping everything in shared_ptr when I serialize out to a file -- I just use .get() on the smart pointer object and serialize the resulting raw pointer. When I serialize in, I read the raw pointer from the serialized file and wrap it in the shared_ptr candy coating at that point. It's a little extra code in the serialization function, but it works.
If I've guessed inaccurately on some of your situation, feel free to add a comment. I'd be happy to help further if I can.
Related
It's rather not a question "how to do it" it's rather "how to do it the right way"
I'm developing an editor in Qt where different widgets display the children and its (member) variables. Each of these widgets should hold a reference/pointer to the edited child to display and change their member variables.
The first attempt was the old ANSI C way I learned (and still kinda stuck in) with simple raw pointer to the used objects. It works fine but since the C++11 standard supports smart pointer and using them is recommended I'm trying to use them.
The problem is, I'm not quite sure what's the "best way" to use them in this case...
After reading Smart Pointers: Or who owns you baby? and Which kind of pointer do I use when? and a few others I came to different conclusions:
The first is to use a*unique_ptr since the edited object is clearly the owner which creates and also deletes its children. The widgets are simply referring to the child to show or change them.
The problem is how should the widgets refer to the child...
for now I'm simply still using a raw pointer I got with the get() method of the unique_ptr but this seems kinda flawed to me.
I still can accidentaly call delete on the pointer and cancel the benefits of the smart pointer.
The second approach is to use a shared_ptr because many objects refer to the child and edit it. Also accidentaly deleting it in one widget would do no harm because it is still owned by other objects.
The problem is they own it. When I want to delete it from the edited object I also have to signal all widgets to delete it before it is really gone. (this again seems flawed and error-prone)
I'm not really content with both ways. Is there a clean(er) way to point to the unique_ptr child of the object? Or am I missing a completely different and better approach to this problem?
Your use case doesn't translate directly to requirements (what if someone else deletes the widget while you're editing it?) but I'll assume you don't need anything beyond a naked pointer.
The Standard Library does not provide any strict pointer-observer class. Among observer entities:
Nullable, mutable pointers of native type (T *)
Non-nullable, non-mutable references of native type (T &)
Non-nullable, mutable references/proxies of class type (std::reference_wrapper<T>)
Nullable, self-validating, mutable pointers to managed objects (std::weak_ptr<T>)
If you want a non-nullable, mutable pointer to a non-managed object, which is a fairly reasonable thing to want, you can roll your own.
But naked pointers aren't that bad. The only difference is that it can be nullptr, and that it doesn't have a nice, long, explicit name inside namespace std.
You want to use a shared_ptr in place of your unique_ptr and weak_ptr's in place of your raw pointers. This will give exactly what you're after. The weak_ptr's will not interfere with the edited object's ability to delete the underlying object.
If you are using Qt, you might consider using the Qt smart pointers instead of std:: smart pointers:
QShardPointer and QWeakPointer
or for QObjects:
QPointer (or QWeakPointer, esp in Qt4)
or to achieve copy-on-write data sharing, Qt container and QString style:
QSharedDataPointer
There are other pointer classes too, but some of the above are most likely to do what you want. Also important, if you have your data in Qt container classes, QStrings or such, they handle their own memory with copy-on-write semantics, and should generally be passed around as plain values (sometimes as references) instead of pointers.
But most importantly, do not use std::unique_ptr or std::shared_ptr with QObjects which have parents, because if the parent deletes the child first, then the std:: pointer will delete it again, crashing the program (other way will work ok, child will notify it's parent that it's deleted). In other words, there's a good chance of subtle bugs if you mix QObjects and std:: pointers, so just don't do it. It's not clear from your question if you are doing it, saying just in case.
There is a proposal for the world's dumbest smart pointer, which is a non-owning pointer. Basically, it is a T* that says "oh, and by the way, I don't claim any ownership over this data".
In this case, you have to manage that the observing/passive/dumb pointer gets reset if the unique_ptr goes away -- half manual lifetime management. Using a raw T* with a name that indicates it is non-owning works just as well prior to having the above.
There are benefits to doing the above, especially when you have objects with dependent lifetime.
If you do not, then a shared_ptr and weak_ptr works. Note, however, that anyone with a weak_ptr can create a new shared_ptr, which could extend the lifetime of the shared object beyond the original shared_ptr. This must happen, as there is otherwise a race condition whereby the user of the weak_ptr ensures its data is valid, then goes to use it, but before they do the shared_ptr's data is destroyed.
So the weak_ptr must either by able to prevent the shared_ptr from being destroyed (blocking in multi-threaded context, causing it to "fail" somehow in single-threaded contexts). "Fail" in this case consists of extending the lifetime, which solves both the multi-threaded and the single-threaded problem.
(The single threaded problem is that you verify the weak_ptr is good, do something that causes the shared_ptr to reset, then continue to want to use the weak_ptr's data without rechecking. Naively, it could be avoided with exceptions, but upon closer inspection you run into problems where you'd have to code all methods to check for deletion before accessing this and throw if this is deleted, a pretty harsh requirement!)
How do pointers work with the concepts of Object oriented programming?
As I understand it (and please recognize, I'm classified as an ID-10T), the main tenet of OOP is containment and keeping management responsibility (memory/implementation/etc.) contained within the class; but when an object's method returns a pointers it seems like we are 'popping' the object. Now, somebody might need to worry about:
Are they supposed to delete the pointer's associated object?
But what if the class still needs the object?
Can they change the object? If so, how? (I recognize const might solve this issue)
and so forth...
It seems the user of the object now needs to know much more about how the class works and what the class expects of the user. It feels like a "cat's out of the bag" scenario which seems to slap in the face of OOP.
NOTE: I notice this is a language independent question; however, I was prompted to ask the question while working in a C++ environment.
What you describe are ownership issues. These are orthogonal (i.e. independent, you can have either without the other or even both) to object orientation. You have the same issues if you do not use OOP and juggle pointers to POD structs. You don't have the issue if you use OOP but solve it somehow. You can (try to) solve it using more OOP or in another way.
They are also orthogonal to the use of pointers (unless you nit pick and extend the definition of pointer). For example, the same issues arise if two separate places hold indices into an array and mutate, resize and ultimately delete the array.
In C++, the usual solution is to select the right smart pointer type (e.g. return a shared pointer when you wish to share the object, or a unique pointer to signify exclusive ownership), along with extensive documentation. Actually, the latter is a key ingredient in any language.
One OOP-related thing you can do to help this is encapsulation (of course, you can have encaptulation just fine without OOP). For instance, don't expose the object at all, only expose methods which query the object under the hood. Or don't expose raw pointers, only expose smart pointers.
For starters... You can't have polymorphism without pointers or
references. In C++, traditionally, objects are copied, and have (for
the most part) automatic storage duration. But copy doesn't work with
polymorphic objects—they tend to get sliced. And OO also often
means identity, which in turn means you don't want copy. So the
solution is for the object to be dynamically allocated, and to pass
around pointers. What you do with them is part of the design:
If the object is logically part of another object, then that object is
responsible for its lifetime, and objects which receive the pointer
should take steps to ensure that they don't use it after the owning
object disappears. (Note that this is true even in languages with
garbage collection. The object won't disappear as long as you've got a
pointer to it, but once the owning object is invalid, the owned object
may become invalid as well. The fact that the garbage collector won't
recycle the memory won't guarantee that the object you point to is
usable.)
If the object is a first class entity itself, rather than being
logically part of another object, then it should probably take care of
itself. Again, other objects which may hold a pointer to it must be
informed if it ceases to exist (or becomes invalid). The use of the
Observer pattern is the usual solution. Back when I started C++, there
was a fashion for "relationship management", with some sort of
management classes where you registered relationships, and which
supposedly ensured that everything worked out OK. In practice, they
either didn't work, or didn't do any more than the simple observer
pattern, and you don't hear any more of them today.
For the most part, your precise questions are part of the contract that
each class has to establish for each of its functions. For true OO
classes (entity objects), you should probably never delete them: that's
there business, not yours. But there are exceptions: if you're dealing
with transactions, for example, a deleted object cannot be rolled back,
so when an object decides to delete itself, it will usually register
this fact with the transaction manager, who will delete it as part of
the commit, once it's established that roll back won't be necessary. As
for changing the object, that's a question of the contract: in a lot of
applications, there are mapping objects, which are used to map an
external identifier of some sort to the object. With the goal, often,
of being able to modify the object.
From my understanding and experience, it generally revolves around what it is that you are trying to do as well as the language using pointers (e.g. C++ vs Objective-C).
Usually, though, in C++ terms, I've found that it's best to return either a reference to a smart pointer (such as std::shared_ptr) by reference (perhaps even const reference, depending on the situation), or simply hide the pointer in the class, and if it NEEDS to be accessed or used by something outside of it, use a getter method which either copies the pointer and returns that, or returns a reference to a pointer (granted, AFAIK ref-to-ptr is only possible in C++). If someone doesn't know that you shouldn't delete a ref-to-ptr in most situations (of course, if its deallocation is handled by the class internally), you should really think twice about whether or not they're ready to be doing C++ stuff on your team.
It's fairly common to just use public references for class members if they can be stack allocated (i.e., if they won't take up too much memory), while managing heap allocated objects internally. If you need to set the class member outside of the class, it's possible to just use a set method which takes the required value, rather than access it directly.
there are already a couple of questions regarding this topic, but I am still not sure what to do: Our codebase uses shared_ptr at many places. I have to admit that we did not define ownership clearly when writing it.
We have some methods like
void doSomething(shared_ptr<MyClass> ptr)
{
//doSomething() is a member function of a class, but usually won't store the ptr
ptr->foo();
...
}
After having discovered the first (indirect) circular dependencies I would like to correct the mistakes in our design. But I'm not exactly sure how. Is there any benefit in changing the method from above to
void doSomething(weak_ptr<MyClass> ptr)
{
shared_ptr<MyClass> ptrShared = ptr.lock();
ptrShared->foo();
...
}
?
I am also confused because some people say (including the Google Style guide) that in the first place it's important to get ownership correct (which would probably mean introduction of many weak_ptrs, e.g. in the example with the methods above, but also for many member variables that we have). Others say (see links below) that you should use weak_ptr to break cyclic dependencies. However, detecting them is not always easy, so I wonder if I really should use shared_ptr until I run into problems (and realize them), and then fix them??
Thanks for your thoughts!
See also
shared_ptr and weak_ptr differences
boost::shared_ptr cycle break with weak_ptr
boost, shared ptr Vs weak ptr? Which to use when?
We did not define ownership clearly.
You need to clearly define who owns what. There's no other way to solve this. Arbitrarily swapping out some uses of shared_ptr with weak_ptr won't make things better.
There is no benefit in changing your design above from shared_ptr to weak_ptr. Getting ownership right is not about using weak_ptrs, it's about managing who stores the shared_ptr for any significant length of time. If I pass a shared_ptr to a method, assuming I don't store that shared_ptr into a field in my object as part of that method, I haven't changed who owns that data.
In my experience the only reason for using weak_ptr is when you absolutely must have a cycle of pointers and you need to break that cycle. But first you should consider if you can modify your design to eliminate the cycle.
I usually discourage mixing shared_ptr's and raw pointers. It inevitably happens (though it probably shouldn't) that a raw pointer needs to be passed to a function that takes a shared_ptr of that type. A weak_ptr can be safely converted to a shared_ptr, with a raw pointer you're out of luck. Even worse, a developer inexperienced with shared_ptr's may create a new shared_ptr from that raw pointer and pass it to the function, causing that pointer to be deleted when the function returns. (I actually had to fix this bug in production code, so yes it does happen :) )
It sounds like you have a design problem. shared_ptr provides
a simple to use implementation for specific design solutions,
but it (nor anything else) can replace the design. Until you
have determined what the actual lifetime of each type of object
should be, you shouldn't be using shared_ptr. Once you've done
that, most of the shared_ptr/weak_ptr issues should disappear.
If, having done that, and determined that the lifetime of some
objects does depend on that of other objects, and there are
cycles in this dependency, you have to determine (at the design
level, again) how to manage those cycles---it's quite possible,
for example, that in those cases, shared_ptr isn't the correct
solution, or that many of the pointers involved are just for
navigation, and should be raw pointers.
At any rate, the answer to your question resides at the design
level. If you have to ask it when coding, then it's time to go
back to design.
Some people are right: you should at first have very clear picture about objects' ownership in your project.
shared_ptrs are shared, i.e. "owned by community". That might or might not be desirable. So I would advise to define ownership model and then to not abuse shared_ptr semantics and use plain pointers whenever ownership should not be "shared" more.
Using weak_ptrs would mask the problem further rather than fix it.
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.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
C++ is all about memory ownership - aka ownership semantics.
It is the responsibility of the owner of a chunk of dynamically allocated memory to release that memory. So the question really becomes who owns the memory.
In C++ ownership is documented by the type a raw pointer is wrapped inside thus in a good (IMO) C++ program it is very rare (rare, not never) to see raw pointers passed around (as raw pointers have no inferred ownership thus we can not tell who owns the memory and thus without careful reading of the documentation you can't tell who is responsible for ownership).
Conversely, it is rare to see raw pointers stored in a class each raw pointer is stored within its own smart pointer wrapper. (N.B.: If you don't own an object you should not be storing it because you can not know when it will go out of scope and be destroyed.)
So the question:
What type of ownership semantic have people come across?
What standard classes are used to implement those semantics?
In what situations do you find them useful?
Lets keep 1 type of semantic ownership per answer so they can be voted up and down individually.
Summary:
Conceptually, smart pointers are simple and a naive implementation is easy. I have seen many attempted implementations, but invariably they are broken in some way that is not obvious to casual use and examples. Thus I recommend always using well tested smart pointers from a library rather than rolling your own. std::auto_ptr or one of the Boost smart pointers seem to cover all my needs.
std::auto_ptr<T>:
Single person owns the object. Transfer of ownership is allowed.
Usage: This allows you to define interfaces that show the explicit transfer of ownership.
boost::scoped_ptr<T>
Single person owns the object. Transfer of ownership is NOT allowed.
Usage: Used to show explicit ownership. Object will be destroyed by destructor or when explicitly reset.
boost::shared_ptr<T> (std::tr1::shared_ptr<T>)
Multiple ownership. This is a simple reference counted pointer. When the reference count reaches zero, the object is destroyed.
Usage: When an object can have multiple owers with a lifetime that can not be determined at compile time.
boost::weak_ptr<T>:
Used with shared_ptr<T> in situations where a cycle of pointers may happen.
Usage: Used to stop cycles from retaining objects when only the cycle is maintaining a shared refcount.
Simple C++ Model
In most modules I saw, by default, it was assumed that receiving pointers was not receiving ownership. In fact, functions/methods abandoning ownership of a pointer were both very rare and explicitly expressed that fact in their documentation.
This model assumes that the user is owner only of what he/she explicitly allocates. Everything else is automatically disposed of (at scope exit, or through RAII). This is a C-like model, extended by the fact most pointers are owned by objects that will deallocate them automatically or when needed (at said objects destruction, mostly), and that the life duration of objects are predictable (RAII is your friend, again).
In this model, raw pointers are freely circulating and mostly not dangerous (but if the developer is smart enough, he/she will use references instead whenever possible).
raw pointers
std::auto_ptr
boost::scoped_ptr
Smart Pointed C++ Model
In a code full of smart pointers, the user can hope to ignore the lifetime of objects. The owner is never the user code: It is the smart pointer itself (RAII, again). The problem is that circular references mixed with reference counted smart pointers can be deadly, so you have to deal both with both shared pointers and weak pointers. So you have still ownership to consider (the weak pointer could well point to nothing, even if its advantage over raw pointer is that it can tell you so).
boost::shared_ptr
boost::weak_ptr
Conclusion
No matter the models I describe, unless exception, receiving a pointer is not receiving its ownership and it is still very important to know who owns who. Even for C++ code heavily using references and/or smart pointers.
For me, these 3 kinds cover most of my needs:
shared_ptr - reference-counted, deallocation when the counter reaches zero
weak_ptr - same as above, but it's a 'slave' for a shared_ptr, can't deallocate
auto_ptr - when the creation and deallocation happen inside the same function, or when the object has to be considered one-owner-only ever. When you assign one pointer to another, the second 'steals' the object from the first.
I have my own implementation for these, but they are also available in Boost.
I still pass objects by reference (const whenever possible), in this case the called method must assume the object is alive only during the time of call.
There's another kind of pointer that I use that I call hub_ptr. It's when you have an object that must be accessible from objects nested in it (usually as a virtual base class). This could be solved by passing a weak_ptr to them, but it doesn't have a shared_ptr to itself. As it knows these objects wouldn't live longer than him, it passes a hub_ptr to them (it's just a template wrapper to a regular pointer).
Don't have shared ownership. If you do, make sure it's only with code you don't control.
That solves 100% of the problems, since it forces you to understand how everything interacts.
Shared Ownership
boost::shared_ptr
When a resource is shared between multiple objects.
The boost shared_ptr uses reference counting to make sure the resource is de-allocated when everybody is finsihed.
std::tr1::shared_ptr<Blah> is quite often your best bet.
From boost, there's also the pointer container library. These are a bit more efficient and easier to use than a standard container of smart pointers, if you'll only be using the objects in the context of their container.
On Windows, there are the COM pointers (IUnknown, IDispatch, and friends), and various smart pointers for handling them (e.g. the ATL's CComPtr and the smart pointers auto-generated by the "import" statement in Visual Studio based on the _com_ptr class).
One Owner
boost::scoped_ptr
When you need to allocate memory dynamically but want to be sure it gets deallocated on every exit point of the block.
I find this usefull as it can easily be reseated, and released without ever having to worry about a leak
I don't think I ever was in a position to have shared ownership in my design. In fact, from the top of my head the only valid case I can think of is Flyweight pattern.
yasper::ptr is a lightweight, boost::shared_ptr like alternative. It works well in my (for now) small project.
In the web page at http://yasper.sourceforge.net/ it's described as follows:
Why write another C++ smart pointer?
There already exist several high
quality smart pointer implementations
for C++, most prominently the Boost
pointer pantheon and Loki's SmartPtr.
For a good comparison of smart pointer
implementations and when their use is
appropriate please read Herb Sutter's
The New C++: Smart(er) Pointers. In
contrast with the expansive features
of other libraries, Yasper is a
narrowly focused reference counting
pointer. It corresponds closely with
Boost's shared_ptr and Loki's
RefCounted/AllowConversion policies.
Yasper allows C++ programmers to
forget about memory management without
introducing the Boost's large
dependencies or having to learn about
Loki's complicated policy templates.
Philosophy
* small (contained in single header)
* simple (nothing fancy in the code, easy to understand)
* maximum compatibility (drop in replacement for dumb pointers)
The last point can be dangerous, since
yasper permits risky (yet useful)
actions (such as assignment to raw
pointers and manual release)
disallowed by other implementations.
Be careful, only use those features if
you know what you're doing!
There is another frequently used form of single-transferable-owner, and it is preferable to auto_ptr because it avoids the problems caused by auto_ptr's insane corruption of assignment semantics.
I speak of none other than swap. Any type with a suitable swap function can be conceived of as a smart reference to some content, which it owns until such time as ownership is transferred to another instance of the same type, by swapping them. Each instance retains its identity but gets bound to new content. It's like a safely rebindable reference.
(It's a smart reference rather than a smart pointer because you don't have to explicitly dereference it to get at the content.)
This means that auto_ptr becomes less necessary - it's only needed to fill the gaps where types don't have a good swap function. But all std containers do.
One Owner: Aka delete on Copy
std::auto_ptr
When the creator of the object wants to explicitly hand ownership to somebody else.
This is also a way documenting in the code I am giving this to you and I am no longer tracking it so make sure you delete it when you are finished.