views:

783

answers:

7

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?

+8  A: 

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.

Johannes Schaub - litb
Similarly, enable_shared_from_this won't allow shared_from_this in a destructor, since the shared_ptr itself is in the process of destructing.
Doug T.
+1  A: 

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).

Nemanja Trifunovic
A: 

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?

Marc
+4  A: 

One example of correct use is return *this; in functions like operator++() and operator<<().

David Thornley
A: 

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.

KeithB
+4  A: 

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.

Brian
A: 

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.

Robert Gould