Thread: delete object from inside object

  1. #1
    Registered User Drogin's Avatar
    Join Date
    Oct 2005
    Location
    Norway
    Posts
    105

    delete object from inside object

    Is it possible to delete an object from inside an object?
    I know this is extremely ugly. I am just curious.

    Something like this:

    Code:
    class Test {
      public:
    void  reload();
    };
    
    void Test::reload() {
      Test *helper = this;
       delete this;
       helper = new Test();
    }
    This is probably all very wrong..I just wrote this code to illustrate what I mean.
    But is it some way to do something similar?

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    It's possible for an object to delete itself, but what you're attempting to do is not possible. An object cannot "reload" itself. What you're doing in reload() is:
    1) Create a temporary pointer "helper" and make it point to the current object.
    2) Delete the current object. Now you may no longer access any member variables or call any functions!
    3) Create a new Test object and have "helper" point to it. This makes the initialization of "helper" a dead store.
    4) Return from the function, leaking the new Test object.

    In particular, what this function does not do is change what "this" points to or what any external pointers to the current object point to (except that they're now invalid).
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #3
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    It is probably not good to "reload" an object since you reallocate memory. You would probably want to have an initializer function and just reinitialize every member variable. But This might work and I don't find ugly.
    Code:
    class Test {
      public:
      void  reload();
    };
    
    Test* Test::reload() {
       delete this;
       return new Test();
    }
    
    //main
    Test* t = new Test();
    t = t.reload();
    The question is if this would work:
    Code:
    void Test::reload() {
       delete this;
       this = new Test();
    }
    which I would bet that wouldn't work...

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    If you want to revert to the default-constructed object you can just assign one to *this.

    Code:
    #include <string>
    #include <iostream>
    
    struct Test
    {
        std::string msg;
        Test(): msg("Life, universe, everything?") {}
    
        void reload()
        {
            *this = Test();
        }
    };
    
    int main()
    {
        Test a;
        std::cout << a.msg << '\n';
        a.msg = "42";
        std::cout << a.msg << '\n';
        a.reload(); //same as: a = Test();
        std::cout << a.msg << '\n';
    }
    (You might also swap current instance with a default-constructed temporary, if you provide an efficient swap method.)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    Why not simply reset the member variables to their default-constructed values (and delete any dynamically-allocated memory within the object)?

  6. #6
    Amazingly beautiful user.
    Join Date
    Jul 2005
    Location
    If you knew I'd have to kill you
    Posts
    254
    Quote Originally Posted by C_ntua View Post
    It is probably not good to "reload" an object since you reallocate memory. You would probably want to have an initializer function and just reinitialize every member variable. But This might work and I don't find ugly.
    Code:
    class Test {
      public:
      void  reload();
    };
    
    Test* Test::reload() {
       delete this;
       return new Test();
    }
    
    //main
    Test* t = new Test();
    t = t.reload();
    The question is if this would work:
    Code:
    void Test::reload() {
       delete this;
       this = new Test();
    }
    which I would bet that wouldn't work...
    Any form of "delete this" is never safe, because the object does not know whether it is allocated on the stack or on the heap. If it is allocated on the stack, first off, the destructor will be called twice (once then, once when the stack unwinds), and second, you are attempting to free memory which you have not allocated, which will most likely result in a segfault.
    Programming Your Mom. http://www.dandongs.com/

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by C_ntua View Post
    Code:
    //main
    Test* t = new Test();
    t = t.reload();
    The question is if this would work:
    Code:
    void Test::reload() {
       delete this;
       this = new Test();
    }
    which I would bet that wouldn't work...
    It does not. this is a const pointers if I am not mistaken.

    Quote Originally Posted by CrazyNorman View Post
    Any form of "delete this" is never safe, because the object does not know whether it is allocated on the stack or on the heap. If it is allocated on the stack, first off, the destructor will be called twice (once then, once when the stack unwinds), and second, you are attempting to free memory which you have not allocated, which will most likely result in a segfault.
    A "delete this" can be safe and can have its uses, but one must be careful in doing so. One thing you must never do is as you mention: never create it on the stack.
    http://www.parashift.com/c++-faq-lit...html#faq-16.15
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    It does not. this is a const pointers if I am not mistaken.
    More importantly, (but less easy to understand for non-language-lawyers,) 'this' is not an lvalue.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Does the actual class you want to do this on follow the rule of three?
    I.e. if it has a copy-constructor, destructor, or assignment operator (and these are needed), does it have all three?
    This is the more important question here. If the class does not follow the rule of three then it is already broken.
    If it does follow the rule of three, and it has a default constructor, then you can trivially do this:
    Code:
    Test t(some, funky, constructor, arguments);
    // or other things done to t...
    
    t = Test(); // Back to defaults again - woo!
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by R.Stiltskin View Post
    Why not simply reset the member variables to their default-constructed values (and delete any dynamically-allocated memory within the object)?
    Sounds like a good plan, and if you do it right, you could re-use the same code for both things:
    Code:
    class Something
    {
       private:
          int x;
          sometype *ptr;
         void Initialize()
         {
             x = 42;
             ptr = NULL;
         }
       public:
         Something()  
         {
             Initialize();
         }
         void Reload()
         {
            Initialize();
         }
    };
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Matsp's show how the problem is generally solved.

    You can principally do something like this:
    Code:
    class Test {
      public:
    void  reload();
    };
    
    void Test::reload() {
       this->~Test();
       new (this) Test();
    }
    But I cannot think of a case where this solution is better.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. synchronization object choosing
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 03-22-2008, 04:33 AM
  2. Replies: 4
    Last Post: 01-23-2008, 06:21 AM
  3. Replies: 60
    Last Post: 12-20-2005, 11:36 PM
  4. Searching STL Map Inside STL Map Object :: C++
    By kuphryn in forum C++ Programming
    Replies: 2
    Last Post: 11-14-2002, 09:11 AM