Thread overview
Beginner: How does an object delete itself?
Sep 21, 2008
nobody
Sep 21, 2008
ylixir
Sep 21, 2008
nobody
Sep 21, 2008
Simen Kjaeraas
Sep 21, 2008
bearophile
Sep 22, 2008
Simen Kjaeraas
Sep 21, 2008
nobody
Sep 21, 2008
Janderson
Oct 03, 2008
Tim M
September 21, 2008
Hello. I just started using OOP and had a question.

I have something like this:

class Foo{
..
    private void deleteMyself()
    {
        this.delete;
        foo.length--;
    }
..
}

Foo[] foo;

But this obviously doesn't work.
The problem is, how do I know what position in the array the object is, and
how do I delete it?
I don't want empty elements in my array.


September 21, 2008
nobody wrote:
> Hello. I just started using OOP and had a question.
> 
> I have something like this:
> 
> class Foo{
> ..
>     private void deleteMyself()
>     {
>         this.delete;
>         foo.length--;
>     }
> ..
> }
> 
> Foo[] foo;
> 
> But this obviously doesn't work.
> The problem is, how do I know what position in the array the object is, and how do I delete it?
> I don't want empty elements in my array. 
> 
> 

you could do some wizardry to get something like that to work, but it sounds like such an awkward situation to be at in the first place. maybe if you posted a little more context around that bit, someone could help you find a design pattern that would eliminate the need to do that altogether.

honestly, in most cases, something like that wouldn't be a good idea. what if the class was used later in something other than an array?
September 21, 2008
On Sun, 21 Sep 2008 17:15:22 +0200, nobody <somebody@somewhere.com> wrote:

> Hello. I just started using OOP and had a question.
>
> I have something like this:
>
> class Foo{
> ..
>     private void deleteMyself()
>     {
>         this.delete;
>         foo.length--;
>     }
> ..
> }
>
> Foo[] foo;
>
> But this obviously doesn't work.
> The problem is, how do I know what position in the array the object is, and
> how do I delete it?
> I don't want empty elements in my array.

class Foo
{
...
    private void deleteMySelf()
    {
        for (int i = 0; i < foo.length; i++)
        {
            if (foo[i] == this)
            {
                // If order is not important, copy last element of array to position i
                //
                //   foo[i] = foo[$-1];
                //
                // If order is important, iterate through rest of array, moving elements one step forward
                //
                //   while (++i < foo.length)
                //   {
                //       foo[i-1] = foo[i];
                //   }
                //
                foo.length--;
            }
        }

        delete this;
    }
...
}


Foo[] foo;

-- 
Simen
September 21, 2008
Simen Kjaeraas:
> // If order is important, iterate through rest of array, moving elements one step forward

I'd like to use the normal D slice syntax for this copying, but you can't, because that syntax can be used only when arrays don't overlap.

Bye,
bearophile
September 21, 2008
Thanks, after some Access Violations in my code I got it to work.

But is this not better?

class Foo
{
...
     private void deleteMySelf()
     {
         for (int i = 0; i < foo.length; i++)
         {
             if (foo[i] == this)
             {
                 foo[i] = foo[$-1];

                 foo.length--;

                 delete this;

                 break; // is this still necessary?
             }
         }
     }
...
}


September 21, 2008
I'm still only a beginner, but this class is only used in one array ;)


"ylixir" <ylixir@gmail.com> wrote in message news:gb5pv5$2f87$1@digitalmars.com...
> nobody wrote:
>> Hello. I just started using OOP and had a question.
>>
>> I have something like this:
>>
>> class Foo{
>> ..
>>     private void deleteMyself()
>>     {
>>         this.delete;
>>         foo.length--;
>>     }
>> ..
>> }
>>
>> Foo[] foo;
>>
>> But this obviously doesn't work.
>> The problem is, how do I know what position in the array the object is,
>> and how do I delete it?
>> I don't want empty elements in my array.
>
> you could do some wizardry to get something like that to work, but it sounds like such an awkward situation to be at in the first place. maybe if you posted a little more context around that bit, someone could help you find a design pattern that would eliminate the need to do that altogether.
>
> honestly, in most cases, something like that wouldn't be a good idea. what if the class was used later in something other than an array?


September 21, 2008
Simen Kjaeraas wrote:
> On Sun, 21 Sep 2008 17:15:22 +0200, nobody <somebody@somewhere.com> wrote:
> 
>> Hello. I just started using OOP and had a question.
>>
>> I have something like this:
>>
>> class Foo{
>> ..
>>     private void deleteMyself()
>>     {
>>         this.delete;
>>         foo.length--;
>>     }
>> ..
>> }
>>
>> Foo[] foo;
>>
>> But this obviously doesn't work.
>> The problem is, how do I know what position in the array the object is, and
>> how do I delete it?
>> I don't want empty elements in my array.
> 
> class Foo
> {
> ...
>     private void deleteMySelf()
>     {
>         for (int i = 0; i < foo.length; i++)
>         {
>             if (foo[i] == this)
>             {
>                 // If order is not important, copy last element of array to position i
>                 //
>                 //   foo[i] = foo[$-1];
>                 //
>                 // If order is important, iterate through rest of array, moving elements one step forward
>                 //
>                 //   while (++i < foo.length)
>                 //   {
>                 //       foo[i-1] = foo[i];
>                 //   }
>                 //
>                 foo.length--;
>             }
>         }
> 
>         delete this;
>     }
> ...
> }
> 
> 
> Foo[] foo;
> 

Personally I wouldn't add a method to the class to remove it from a list.  Why? Because then your coupling the array to that object.  Its far better to write a free function to do it:

void Remove(inout F[] array, F element)
{
	for (int i=0; i<array.length; ++i)
	{
		if (array[i] == element)
		{
			array = array[0..i] ~ array[i+1..$];
			break;
		}
	}
}

Ok, what the hell, lets make it a template:

void Remove(F)(inout F[] array, F element)
{
	for (int i=0; i<array.length; ++i)
	{
		if (array[i] == element)
		{
			array = array[0..i] ~ array[i+1..$];
			break;
		}
	}
}

Now it'll work on any array.

Also if your deleting more then one element in an array you can simply iterate backwoods to solve the i shifting to the wrong place problem:

	for (int i=array.length; --i>=0; )
	{
		if (isTypeLookingFor(array[i]))
		{
			array = array[0..i] ~ array[i+1..$];
		}
	}

-Joel
September 21, 2008
"nobody" wrote
> Thanks, after some Access Violations in my code I got it to work.
>
> But is this not better?
>
> class Foo
> {
> ...
>     private void deleteMySelf()
>     {
>         for (int i = 0; i < foo.length; i++)
>         {
>             if (foo[i] == this)

A warning for the beginner, be careful with ==.  Use 'is' to check for identity (i.e. the exact same instance).  If you don't, you may end up with segmentation faults:

               if(foo[i] is this)
>             {
>                 foo[i] = foo[$-1];
>
>                 foo.length--;
>
>                 delete this;
>
>                 break; // is this still necessary?
>             }
>         }
>     }
> ...
> }

Like others, I think this seems like a bad design.  What is wrong with using the garbage collector?  And what's wrong with using an external class/function to keep track of the Foo's?  If you wanted to change at some point your foo array to another type of container instead of an array, your function wouldn't work, so Foo is stuck being only in an array.

-Steve


September 22, 2008
On Sun, 21 Sep 2008 18:31:07 +0200, bearophile <bearophileHUGS@lycos.com> wrote:

> Simen Kjaeraas:
>> // If order is important, iterate through rest of array, moving elements one step forward
>
> I'd like to use the normal D slice syntax for this copying, but you can't, because that syntax can be used only when arrays don't overlap.
>
> Bye,
> bearophile

I guess one could use memmove, if one wanted. But as you say, slices would be neater.

-- 
Simen
October 03, 2008
On Mon, 22 Sep 2008 03:15:22 +1200, nobody <somebody@somewhere.com> wrote:

> Hello. I just started using OOP and had a question.
>
> I have something like this:
>
> class Foo{
> ..
>     private void deleteMyself()
>     {
>         this.delete;
>         foo.length--;
>     }
> ..
> }
>
> Foo[] foo;
>
> But this obviously doesn't work.
> The problem is, how do I know what position in the array the object is, and
> how do I delete it?
> I don't want empty elements in my array.
>
>


By now I assume you understand that was a bad idea but the replies don't seem to go into much detail why. If you have one process and that process is only making use of the initial thread, no other threads are cretaed. Then when this method gets called to delete self and the object is deleted, where doe's the next line of code execution occur?

A way to make something like that work would be to have each running in there own thread and then they delete there own thread. If no other threads have a reference to the same object then the garbage collecor cleans up for you. Another way is provide your own delete self which just removes references to itself from other classes and the gc will then clean it up again.