Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
What are some of the main reasons to use raw pointers in 2014, given that the C++11 standard is now well supported by most decent compilers?
I identified a couple of scenarios :
You are extending a legacy codebase that makes heavy use of raw pointers, and you would like to maintain consistency in style.
You are using a library that only exports raw pointers, but I guess you could still make use of casts.
You want to exploit pointers's capability to provide multiple levels of indirection. (I do not know C++11 well enough to know if this can be achieved using smart pointers, or using some other techniques.)
What other scenarios do you think are appropriate for use of pointers?
Would you even recommending learning about pointers in general, today?
I can imagine circumstances where you have a statically-allocated array and you want to use a raw pointer to iterate through it in high-performance code. There's still nothing wrong with this.
Your #1 is true.
Your #2 is possibly not right: if you're "making use of casts" to transform raw pointers owned by a third-party library, into smart pointers (implying local ownership) then something has gone horribly wrong.
Your #3 is technically true but avoid this whenever you can.
What is not recommended nowadays is playing with raw pointers to your own, dynamically-allocated memory. That is, the advice is to avoid new without smart pointers (and the corollary is that you shouldn't need delete).
Everybody is against raw pointers as it's way too easy to leak them.
But you can use raw pointers to point to data owned somewhere else... just don't new/delete them. Use std::unique_ptr or std::shared_ptr for that. Or for dumb (POD) memory buffers use std::vector<unsigned char>, don't malloc and free yourself.
Think of a std::vector<heavy_object*> when you need to juggle with sub-selections of objects that are non-trivial to copy but already exist elsewhere. You need pointers for this.
You also need pointers in functions for optional arguments where references don't cut it as you want to be able to pass a nullptr.
Pointers to consecutive objects can also be iterated easily without any std::iterator overhead. Just ++ or -- and that's it. I often use direct pointer iteration instead of begin, end for vectors.
As you understand how they work... you'll need them a lot and you'll use them properly.
Smart pointers are used for handling object ownership issues, but not all pointers are used to deal with object ownership. For example it makes more sense to pass raw pointer to a function if you are not planning to pass ownership to this function (i.e. you just want the function to deal with the data addressed by the pointer)
IMHO Raw pointers still have their place.
What C++11 gives us is the ability to manage the lifespan of raw pointers so that we don't have to delete them ourselves.
There is nothing wrong with using raw pointers as long as they are managed by a smart pointer/pointer manager in the correct scope or frame to ensure their lifespan is correct. If that is true then you never have to delete a raw pointer and you can safely use them within the scope/frame throughout which their life-time is guaranteed.
I would say, if possible, store a raw pointer to your new object in a std::unique_ptr if its lifespan should be controlled by a given scope/frame. Once that is done use the raw pointer within that scope frame. Just never delete it;
Sometimes it is not possible to manage the lifespan of a new object from a single scope or frame. In this case use a std::shared_ptr in every scope/frame that independently needs to manage the lifespan of the new object. Then, within each scope/frame, there is no reason not to use the raw-pointer just like when it is being managed by a std::unique_ptr.
So there is often no reason to incur the speed disadvantage of smart pointers as one of their strengths lies in managing the life-span of the new object in order to ensure the validity of the raw-pointer and the automatic destruction of its object when its no longer needed.
There are other times when a raw pointer is not appropriate.
For example when a managed pointer needs to transfer "ownership" to another scope/frame. That is when you need the scope/frame responsible for managing the life-span of the new object to change. In these cases avoid raw pointers like the plague!
What other scenarios do you think are appropriate for use of pointers?
One of the main scenarios in which raw pointers are used is when you have non-owning pointers. Typically, where a reference would work, but you want to avoid the constraints of a reference (non-reseatable, non-copyable). You could use a reference_wrapper type in those cases, but it's simpler to just use a raw pointer instead. Smart-pointers encode ownership (who creates and destroys the object), so, if there is no ownership to encode (because it is implied otherwise), then a raw pointer is OK.
Just to make it clear, typical examples of what I just explained are things like:
temporary copyable functors that need a pointer to some object that it doesn't own.
internal cross-links within a data structure (e.g., "back pointers").
But it's important to notice that these things should not, in general, be present in interfaces. Generally, you can avoid raw pointers pretty much completely in interfaces (e.g., library functions and classes), and only really use them internally, i.e., in library-side code, not in user-side code. In other words, if you need to use raw pointers, hide them away.
Raw pointers are also sometimes seen for optional function parameters, where you can pass in a nullptr if you don't want that result.
The main thing that should be avoided, and can be avoided in general, is naked new / delete calls in user-side code. A typical good modern C++ library (and even more so with C++11) will not have any such naked new / delete occurrences, and that's a fact.
Raw pointers are not so much a problem by themselves, what is problematic is (1) manual memory management, and (2) ownership management (which is problematic if raw pointers are used instead of smart-pointers).
Would you even recommending learning about pointers in general, today?
Of course you should learn about pointers. They are essential to understanding programming, and to learning to write library-side code. Raw pointers are still very present in the guts of a lot of library code and such, even if you don't see them.
common reasons to use raw pointers off the top of my head.
Reading and parsing binary files
Interacting directly with hardware
Arrays?
Speed. AFAIK Smart pointers are slower than raw pointers and there are relatively safe ways to use raw pointers. See Chromium's code base for example or WebKit's. Both use various kinds of tracked memory without the full overhead of smart pointers. Of course with limitations as well.
Related
Are there any reasons to still use raw pointers (for managed resources) in C++11/14?
Should resource member variables in a class be held in their own smart pointers for automatic RAII without need for cleanup in destructor?
Is the implementation of smart pointers inlined that there is no overhead in doing so?
Are there any reasons to still use raw pointers (for managed
resources) in C++11/14?
I assume that by "managed resources" you mean "owned resources".
Yes there are reasons:
As you are inferring in your question, sometime you want to refer to an object or none, and it can change through time. You have to use a raw pointer in this case, because there is no alternative right now in this specific case. There might be later as there is a proposal about adding a "dumb" non-owning pointer which just clarify the role of the pointer (observe/refer, not own). Meanwhile the recommendation is to avoid new/delete if you can and use raw pointer only as "refers to without owning" kind of re-assignable reference.
You still need raw pointers for implementation of non-raw pointers and any low level RAII construct. Not everybody needs to work on fundamental libraries, but of course if you do, then you need basic constructs to work with. For example in my domain I often have to build up custom "object pool" systems in different ways. At some point in the implementation you have to manipulate raw memory which are not objects yet, so you need to use raw pointers to work with that.
When communicating with C interfaces, you have no other choices than to pass raw pointers to functions taking them. A lot of C++ developers have to do this, so it's just in some very specific regions of your code that you will have to use them.
Most companies using C++ don't have a "modern C++" experience of C++ and work with code that use a lot of pointers where it is not actually necessary. So most of the time when you add code to their codebase, you might be forced by the code-environment, politics, peer-pressure and conventions of the company to use pointers where in a more "modern c++" usage kind of company it would not pass peer-review. So consider the political/historic/social/knowledge-base-of-coworkers context too when choosing your techniques. Or make sure companies/projects you work in match your way of doing things (this might be harder).
Should resource member variables in a class be held in their own smart
pointers for automatic RAII without need for cleanup in destructor?
Resource member variables, in the best case, should just be members without being obvious pointers, not even smart pointers. Smart pointers are a "bridge" between code manipulating raw pointers and pure RAII style. If you have total control over some code and it's new code, you can totally avoid making any use of smart pointer in your interfaces. Maybe you will need them in your implementations though. Keep in mind that there is no actual rules, only recommendations of what you could result in if you
Is the implementation of smart pointers inlined that there is no
overhead in doing so?
Implementation of standard smart pointers is as efficient as they can be so yes most of their code is inlined. However, they are not always free, it depends on what they actually do. For example, in almost all cases, unique_ptr is exactly one raw pointer, with just additional checks around it's places of use. So it's "free". shared_ptr on the other hand have to maintain a counter of how many other shared_ptr refer to the same object. That counter can be changed on several threads doing copies of the shared_ptr, so it have to be atomic. Changing the value of atomic counters is not always free, and you should always assume that there is a higher cost than copying a raw pointer.
So "it depends".
Just:
use RAII as much as you can, without exposing any kind of pointer in your interfaces (smart or not);
use standard smart pointers in implementations if you must use owning pointers;
use raw pointers only if you need to refer to object, null, or other objects changing through time, without owning them;
avoid raw pointers in interfaces except in case of allowing passing optional objects (when nullptr is a correct argument);
You will end-up with code that, from the user's perspective, don't seem to manipulate pointers. If you have several layers of code following these rules, the code will be easier to follow and highly maintainable.
On a related note from: When to use references vs. pointers
Avoid pointers until you can't.
Also note that Sean Parents in his recent talks also consider smart pointers to be raw pointers. They can indeed be encapsulated as implementation details of value-semantic types corresponding to the actual concept being manipulated. Additionally using type-erasure techniques in implementations but never exposing them to the user helps extensibility of some library constructs.
It depends. If the object is fully owned, constructed and destructed by another object, there is a good case for using an std::unique_ptr in that other object. If you have an object which owns several such objects, all of which are dynamically allocated in the constructor, then you have to do something; if the semantics of the usual smart pointers isn't appropriate (which is often the case), then you'll have to invent something: in the case of a graph, for example, you might put the root pointer in a base class (initializing it to null), and have the destructor of the base class clean-up the graph, starting at the root.
Of course, unless your class has some sort of dynamic structure like a graph, you might ask yourself why it is using dynamic allocation to begin with. There are special cases (where, for example, the owned object is polymorphic, and its actual type depends on arguments to the constructor), but in my experience, they aren't that common. In practice, there just aren't that many cases where a smart pointer can be used in an object, much less should be used.
RAII is more than just wrapping up new and delete - a smart pointer is a form of RAII but RAII is a lot more than that. A good candidate for RAII is when you have any sort of mirroring functions: new/delete, initialise/teardown, stop/start. So your resource should still have its own RAII class - one that performs its cleanup function in its own destructor.
More and more I hear, that I should use smart pointers instead of naked pointers, despite I have effective memory leak system implemented.
What is the correct programming approach on using smart pointers please? Should they really be used, even if I check memory leaks on allocated memory blocks? Is it still up to me? If I do not use them, can this be considered as programming weakness?
If the smart pointers(ex: std::auto_ptr) are strongly recommended, should I use them instead of every naked pointer?
You should use RAII to handle all resource allocations.
Smart pointers are just one common special case of that rule.
And smart pointers are more than just shared_ptr. There are different smart pointers with different ownership semantics. Use the one that suits your needs. (The main ones are scoped_ptr, shared_ptr, weak_ptr and auto_ptr/unique_ptr (prefer the latter where available). Depending on your compiler, they may be available in the standard library, as part of TR1, or not at all, in which case you can get them through the Boost libraries.
And yes, you should absolutely use these. It costs you nothing (if done correctly, you lose zero performance), and it gains you a lot (memory and other resources are automatically freed, and you don't have to remember to handle it manually, and your code using the resource gets shorter and more concise)
Note that not every pointer usage represents some kind of resource ownership, and so not all raw pointer usage is wrong. If you simply need to point to an object owned by someone else, a raw pointer is perfectly suitable. But if you own the object, then you should take proper ownership of it, either by giving the class itself RAII semantics, or by wrapping it in a smart pointer.
You can't just blindly substitute std::auto_ptr for every raw pointer. In particular, auto_ptr transfers ownership on assignment, which is great for some purposes but definitely not for others.
There is a real reason there are several varieties of smart pointers (e.g., shared_ptr, weak_ptr, auto_ptr/unique_ptr, etc.) Each fulfills a different purpose. One major weakness of a "raw" pointer is that it has so many different uses (and has that versatility largely because it does little or nothing to assist in any one purpose). Smart pointers tend to be more specialized, which means they can be more intelligent about doing one thing well, but also means you have to pick the right one for the job or it'll end up dong the wrong things entirely.
Smart pointers allows to define automatically the life-time of objects it refers to. That's the main thing to understand.
So, no, you shouldn't use smart pointers everywhere, only when you want to automate life-time of your objects instead of having, for example, an object managing those objects inside from birth to death. It's like any tool : it solves specific kind of problems, not all problems.
For each object, you should think about the life cycle it will go through, then choose one of the simplest correct and efficient solution. Sometimes it will be shared_ptr because you want the object to be used by several components and to be automatically destroyed once not used anymore. Sometimes you need the object only in the current scope/parent-object, so scoped_ptr might be more appropriate. Sometimes you need only one owner of the instance, so unique_ptr is appropriate. Maybe you'll find cases where you know an algorithm that might define/automate the lifetime of an object, so you'll write your own smart pointer for it.
For example of opposite case, using pools forbids you to use smart_ptr. Naked pointers might be a more welcome simple and efficient solution in this particular (but common in embedded software) case.
See this answer (from me) for more explainations : https://softwareengineering.stackexchange.com/questions/57581/in-c-is-it-a-reflection-of-poor-software-design-if-objects-are-deleted-manuall/57611#57611
Should they really be used, even if I check memory leaks on allocated memory blocks?
YES
The whole purpose of smart pointers is, it help you implement RAII(SBRM), which basically lets the resource itself take the responsibility of its deallocation and the resource doesn't have to rely on you explicitly remembering to deallocate it.
If I do not use them, can this be considered as programming weakness?
NO,
It is not a weakness but a inconvenience or unnecessary hassle to explicitly manage the resources by yourself if you are not using Smart pointers(RAII). The purpose of smart pointers to implement RAII is to provide efficient and hassle free way of handling resources and you would just not be making use of it if you are not using it. It is highly recommended to use it purely for the numerous advantages it provides.
If the smart pointers(ex: std::auto_ptr)are strongly recommended, should I use them instead of every naked pointer?
YES
You should use smart pointers wherever possible because simply there is no drawback of using them and just numerous advantages to use them.
Don't use auto_ptr though because it is already deprecated!! There are various other smart pointers available that you can use depending on the requirement. You can refer the link above to know more about them.
It's a tricky question, and the fact that there is currently a mode to
use smart pointers everywhere doesn't make things any easier. Smart
pointers can help in certain situations, but you certainly can't just
use them everywhere, without thinking. There are many different types
of smart pointers, and you have to think about which one is appropriate
in every case; and even then, most of your pointers (at least in typical
applications in the domains I've worked in) should be raw pointers.
Regardless of the approach, several points are worth mentionning:
Don't use dynamic allocation unless you have to. In many
applications, the only things that need to be allocated dynamically
are objects with specific lifetimes, determined by the application
logic. Don't use dynamic allocation for objects with value semantics.
With regards to entity object, those which model something in the
application domain: these should be created and destructed according
to the program logic. Irregardless of whether there are pointers to
them or not. If their destruction causes a problem, then you have an
error in your program logic somewhere (not handling an event correctly,
etc.), and using smart pointers won't change anything.
A typical example of an entity object might be client connection in a
server, is created when the client connects, and destructed when the
client disconnects. In many such cases, the most appropriate management
will be a delete this, since it is the connection which will receive
the disconnection event. (Objects which hold pointers to such an object
will have to register with it, in order to be informed of its
destruction. But such pointers are purely for navigation, and shouldn't
be smart pointers.)
What you'll usually find when people try to use smart pointers
everywhere is that memory leaks; typical reference counters don't
handle cycles, and of course, typical applications are full of cycles: a
Connection will point to the Client which is connected to it, and
the Client will contain a list of Connection where it is connected.
And if the smart pointer is boost::shared_ptr, there's also a definite
risk of dangling pointers: it's far to easy to create two
boost::shared_ptr to the same address (which results in two counters
for the references).
If the smart pointers(ex: std::auto_ptr) are strongly recommended, should I use them instead of every naked pointer?
In my opinion, yes, you should it for every pointer that you own.
Here are my ideas on resource management in C++ (feel free to disagree):
Good resource management requires thinking in terms of ownership.
Resources should be managed managed by objects (RAII).
Usually single ownership is preferred over shared ownership.
Ideally the creator is also the owner of the object. (However, there are situations where ownership transfer is in order.)
This leads to the following practices:
Make boost::scoped_ptr the default choice for local and member variables. Do keep in mind that using scoped_ptr for member variables will make your class non-copyable. If you don't want this see next point.
Use boost::shared_ptr for containers or to enable shared ownership:
// Container of MyClass* pointers:
typedef boost::shared_ptr<MyClass> MyClassPtr;
std::vector<MyClassPtr> vec;
The std::auto_ptr (C++03) can be used for ownership transfer. For example as the return value of factory or clone methods:
// Factory method returns auto_ptr
std::auto_ptr<Button> button = Button::Create(...);
// Clone method returns auto_ptr
std::auto_ptr<MyClass> copy = obj->clone();
// Use release() to transfer the ownership to a scoped_ptr or shared_ptr
boost::scoped_ptr<MyClass> copy(obj->clone().release());
If you need to store a pointer that you don't own then you can use a raw pointer:
this->parent = inParentObject;
In certain situations a boost::weak_pointer is required. See the documentation for more information.
In general you should prefer smart pointers, but there are a couple of exceptions.
If you need to recast a pointer, for example to provide a const version, that becomes nearly impossible with smart pointers.
Smart pointers are used to control object lifetime. Often when you are passing a pointer to a function, the function will not affect the lifetime; the function does not try to delete the object, and it does not store a copy of the pointer. The calling code cannot delete the object until the function returns. In that case a dumb pointer is perfectly acceptable.
Yes. Assuming you have C++0x available to you, use unique_ptr or shared_ptr (as appropriate) to wrap all the raw pointers you new up. With the help of make_shared, shared_ptr is highly performant. If you don't need reference counting then unique_ptr will get you better perf. Both of them behave properly in collections and other circumstances where auto_ptr was a dumb pointer.
Using smart pointers (shared_ptr or otherwise) EVERYWHERE is a bad idea. It's good to use shared_ptr to manage the lifetime of objects/resources but it's not a good idea to pass them as parameters to functions etc. That increases the likelihood of circular references and other extremely hard to track bugs (Personal experience: Try figuring out who should not be holding onto a resource in 2 millions lines of code if every function invocation changes the reference count - you will end up thinking the guys who do this kind of thing are m***ns). Better to pass a raw pointer or a reference.
The situation is even worse when combined with lazy instantiation.
I would suggest that developers should know the lifecycle of the objects they write and use shared_ptr to control that (RAII) but not extend shared_ptr use beyond that.
I have a C++ application which makes extensively use of pointers to maintain quite complex data structures. The application performs mathematical simulations on huge data sets (which could take several GB of memory), and is compiled using Microsoft's Visual Studio 2010.
I am now reworking an important part of the application. To reduce errors (dangling pointers, memory leaks, ...) I would want to start using smart pointers. Sacrificing memory or performance is acceptible as long as it is limited.
In practice most of the classes are maintained in big pools (one pool per class) and although the classes can refer to each other, you could consider the pool as owner of all the instances of that class. However, if the pool decides to delete an instance, I don't want any of the other classes that still refers to the deleted instance to have a dangling pointer.
In another part I keep a collection of pointers to instances that are delivered by other modules in the application. In practice the other modules maintain ownership of the passed instance, but in some cases, modules don't want to take care of the ownership and just want to pass the instance to the collection, telling it "it's yours now, manage it".
What is the best way to start introducing smart pointers? Just replacing pointers [at random] with smart pointers doesn't seem a correct way, and probably doesn't deliver all the (or any of the) advantages of smart pointers. But what is a better method?
Which types of smart pointers should I further investigate? I sometimes use std::auto_ptr for the deallocation of locally allocated memory, but this seems to be deprected in C++0x. Is std::unique_ptr a better alternative? Or should I go straight to shared pointers or other types of smart pointers?
The question Replacing existing raw pointers with smart pointers seems similar but instead of asking how easy it is, I am asking what the best approach would be, and which kind of smart pointers are suited best.
Thanks in advance for your ideas and suggestions.
I recommend using unique_ptr when possible (this may require some program analysis) and shared_ptr when this is impossible. When in doubt, use a shared_ptr to maximize safety: when handing off control to a container, the reference count will simply go to two and then back to one and the container will eventually delete the associated object automatically. When performance becomes an issue, consider using boost::intrusive_ptr.
Here are the 3 varieties found in the new C++11 standard (unique_ptr replaces auto_ptr)
http://www.stroustrup.com/C++11FAQ.html#std-unique_ptr
http://www.stroustrup.com/C++11FAQ.html#std-shared_ptr
http://www.stroustrup.com/C++11FAQ.html#std-weak_ptr
You can read the text for each pointer and there is an explanation of when to use which in there. For local memory management unique_ptr is the choice. It is non-copyable but movable so as you move it around the receiver takes ownership of it.
Shared_ptr is used if you want to share an object instance around with no one really owning the object and to make sure it doesn't get deleted while someone still has a reference to it. Once the last user of an object destroys the shared_ptr container, the contained object will be deleted.
weak_ptr is used in conjunction with shared_ptr. It enables one to "lock" to see if the reference shared_ptr object still exists before trying to access the internal object.
I'm curious as I begin to adopt more of the boost idioms and what appears to be best practices I wonder at what point does my c++ even remotely look like the c++ of yesteryear, often found in typical examples and in the minds of those who've not been introduced to "Modern C++"?
I don't use shared_ptr almost at all, because I avoid shared ownership in general. Therefore, I use something like boost::scoped_ptr to "own" an object, but all other references to it will be raw pointers. Example:
boost::scoped_ptr<SomeType> my_object(new SomeType);
some_function(my_object.get());
But some_function will deal with a raw pointer:
void some_function(SomeType* some_obj)
{
assert (some_obj);
some_obj->whatever();
}
Just a few off the top of my head:
Navigating around in memory-mapped files.
Windows API calls where you have to over-allocate (like a LPBITMAPINFOHEADER).
Any code where you're munging around in arbitrary memory (VirtualQuery() and the like).
Just about any time you're using reinterpret_cast<> on a pointer.
Any time you use placement-new.
The common thread here is "any situation in which you need to treat a piece of memory as something other than a resource over which you have allocation control".
These days I've pretty much abandoned all use of raw pointers. I've even started looking through our code base for places where raw pointers were used and switched them to a smart pointer variant. It's amazing how much code I've been able to delete by doing this simple act. There is so much code wasted on lifetime management of raw C++ pointers.
The only places where I don't use pointers is for a couple of interop scenarios with other code bases I don't have control over.
I find the primary difference between 'modern' C++ and the old* stuff is careful use of class invariants and encapsulation. Well organised code tends naturally to have fewer pointers flying around. I'm almost as nervous swimming in shared_ptrs as I would be in news and deletes.
I'm looking forward to unique_ptr in C++0x. I think that will tidy away the few (smart) pointers that do still roam the wild.
*still unfortunately very common
Certainly any time you're dealing with a legacy library or API you'll need to pass a raw pointer, although you'll probably just extract it from your smart pointer temporarily.
In fact it is always safe to pass a raw pointer to a function, as long as the function does not try to keep a copy of the pointer in a global or member variable, or try to delete it. With these restrictions in place, the function cannot affect the lifetime of the object, and the only reason for a smart pointer is to manage the object lifetime.
I still use regular pointers in resource-sensitive code or other code that needs tiny footprint, such as certain exceptions, where I cannot assume that any data is valid and must also assume that I am running out of memory too.
Managed memory is almost always superior to raw otherwise, because it means that you don't have to deal with deleting it at the right place, but still have great control over the construction and destruction points of your pointers.
Oh, and there's one other place to use raw pointers:
boost::shared_ptr<int> ptr(new int);
I still use raw pointers on devices that have memory mapped IO, such as embedded systems, where having a smart pointer doesn't really make sense because you will never need or be able to delete it.
If you have circular data structures, e.g., A points to B and B points back to A, you can't use naively use smart pointers for both A and B, since then the objects will only be freed extra work. To free the memory, you have to manually clear the smart pointers, which is about as bad as the delete the smart pointers get rid of.
You might thing this doesn't happen very often, but suppose you have Parent object that has smart pointers to a bunch of Child objects. Somewhere along the way someone needs to look up a the Parent for a Child, so they add a smart pointer member to Child that points back to the parent. Silently, memory is no longer freed.
Some care is required. Smart pointers are not equivalent to garbage collection.
I'm writing C++ that has to co-exist with Objective C (using Objective C++ to bridge).
Because C++ objects declared as part of Objective C++ classes don't have constructors or destructors called you can't really hold them there in smart pointers.
So I tend to use raw pointers, although often with boost::intrustive_ptr and an internal ref count.
Not that I would do it, but you need raw pointers to implement, say, a linked list or a graph. But it would be much smarter to use std::list<> or boost::graph<>.
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.