tags:

views:

295

answers:

6
Class A
{
  public:
    NullIt()
    {
      this = NULL;
    }

    Foo()
    {
      NullIt();
    }
}

A * a = new A;
a->Foo();

assert(a);  //should assert here

Is there a way to achieve this effect, memory leaks aside?

+6  A: 

Exactly what effect are you trying to acheive?

Even if you could assign a new pointer (or NULL) to 'this' (which you can't), it wouldn't affect the pointer 'a'.

Michael Burr
Add to that, I thought that "this" was actually a hidden variable in the argument list of the "method" (really a function under-the-hood) hence it's re-assigned whenever a method is called, just like any other function argument? This however may be compiler-dependent.
Kevin
+3  A: 

this is a constant pointer. You can change what it points to but you can't change the pointer itself.

As noted in comments, yes, you can cast the const away, but even if you change that, it's just a local variable. It won't affect the actual outside reference.

Mehrdad Afshari
You can always get around that with a typecast. Not that it would do you any good, of course.
Mark Ransom
+1  A: 

I can't see any reason you would ever want to do this. It would cause a memory leak, as a would be floating around presumably without any pointers to it. And I'm almost certain you can't assign to this anyway, largely because it doesn't make any sense. Why do you want to do it?

Nick Lewis
+5  A: 

No. The object knows nothing about the external references to it (in this case, "a"), so it can't change them.

If you want the caller to forget your object, then you can do this:

class MyClass
{
    void Release(MyClass **ppObject)
    {
        assert(*pObject == this);   // Ensure the pointer passed in points at us
        *ppObject = NULL;           // Clear the caller's pointer
    }
}


MyClass *pA = new A;
pA->Release(&pA);
assert(pA);               // This assert will fire, as pA is now NULL

When you call Release, you pass in the pointer you hold to the object, and it NULLs it out so that after the call, your pointer is NULL.

(Release() can also "delete this;" so that it destroys itself at the same time)

Jason Williams
yes, this is exactly what I needed. The object itself can only handle the references given to it rather than figuring it out from the this ptr.
BuckFilledPlatypus
You might want to make Release a global function - this avoids the "use the pointer twice". Still, a strange pattern - what about multiple references?
peterchen
@peterchen Making Release global would mean you couldn't check it against 'this' (there wouldn't be a 'this') and without the double indirection, there's no way to affect the pointer value in the caller's scope anyway.
Nick Meyer
@peterchen I always set dead pointers to NULL ("SafeDelete"). I use this pattern a lot in trees, for example. When you delete a tree node/subtree, it can clean up all the internal tree links, but the caller has to pass in a pointer in order to say which node/subtree must be deleted on the first place. Rather than assuming that the caller will forget that pointer, you force them to hand it over to you so you can ensure it is NULLed.
Jason Williams
+1  A: 

Think about why the following won't do what you want:

A *a = new A;
A *b = a;
a = NULL;
assert(b);

and you'll see why setting this to NULL won't work.

Niki Yoshiuchi
+1  A: 

The 'this' pointer is simply the address of the instance of the object your code is in. Setting this = null; isn't allowed because it doesn't make sense. It would appear your looking for

Class A
{
  public:
    ~A
   {
      // clean up A
   }
}

A * a = new A;
delete a;

assert(a);  //should assert here

This will free the instance from memory. However if you have any other references to a, those pointers will still be pointing where that instance was (not good!) and need to be set to null.

Ziplin
Delete doesn't zero out the pointer (which may not be modifiable in any case). I'd suggest setting it to 0 yourself.
David Thornley