www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Object arrays in D

reply "CrudOMatic" <crudomatic gmail.com> writes:
The D documentation is a little lacking in a lot of areas. I'm 
needing to know an exact way of making arrays of objects.

For example:

/* Deck class */
	// Will be adjusted with the proper cards for each game type
	class Deck {
		/* Card count - used to keep track of how many cards are left 
in the deck - when zero, Deck is discarded from the Shoe */
		int cardCount;
		/* Cards array - initialized to cardCount elements */
		Card cards[];
		
		/* Constructor */
		this(int no_cards) {
			cardCount = no_cards;
			cards = new Card[cardCount];
		}
		
		/* Destructor */
		~this() {
			delete cards;
		}
	}

the cards[] array is meant to be an array of Card objects, and 
I'm initializing it in the constructor as seen above. This hasn't 
been tested yet, but I'm needing to know if this is the correct 
way of doing it - to save headaches later.

Also, while I'm here, how would you go about moving objects from 
the cards array in the Deck class to another class containing a 
cards array - I'm talking about MOVING them, not COPYING them. I 
don't want any issues with references being destroyed after being 
moved to another class when I happen to destroy an instance of 
the Deck class.
Apr 10 2012
next sibling parent simendsjo <simendsjo gmail.com> writes:
On Tue, 10 Apr 2012 09:41:28 +0200, CrudOMatic <crudomatic gmail.com>  
wrote:

 The D documentation is a little lacking in a lot of areas. I'm needing  
 to know an exact way of making arrays of objects.

 For example:

 /* Deck class */
 	// Will be adjusted with the proper cards for each game type
 	class Deck {
 		/* Card count - used to keep track of how many cards are left in the  
 deck - when zero, Deck is discarded from the Shoe */
 		int cardCount;
 		/* Cards array - initialized to cardCount elements */
 		Card cards[];
 		
 		/* Constructor */
 		this(int no_cards) {
 			cardCount = no_cards;
 			cards = new Card[cardCount];
 		}
 		
 		/* Destructor */
 		~this() {
 			delete cards;
 		}
 	}

 the cards[] array is meant to be an array of Card objects, and I'm  
 initializing it in the constructor as seen above. This hasn't been  
 tested yet, but I'm needing to know if this is the correct way of doing  
 it - to save headaches later.

 Also, while I'm here, how would you go about moving objects from the  
 cards array in the Deck class to another class containing a cards array  
 - I'm talking about MOVING them, not COPYING them. I don't want any  
 issues with references being destroyed after being moved to another  
 class when I happen to destroy an instance of the Deck class.

In D, arrays includes the number of elements in the array. Card[] cards; assert(cards.length == 0); // Automatically initialized to 0 elements cards.length = cardCount; // cards gets cardCount of null elements cards.reserve(cardCount); // This just extends the array without filling with null elements. cards.length stays at 0 D includes array slices - a view into an array. This way, you can reference cards without copying them. auto other = cards[1..$-1]; // all but first and last card I'll let someone else answer the moving part as I'm not sure how that could be done. The delete statement is going away. You should use clear(cards) instead. This really isn't needed as Ds GC will take care of it eventually. Your example could be written as class Deck { Card[] cards; property int cardCount() { return cards.length; } this(int no_cards) { cards.reserve(no_cards); } } Arrays are more complicated than they seem at first. I recommend you read this article: http://dlang.org/d-array-article.html D has a newsgroup, .learn, for beginner questions.
Apr 10 2012
prev sibling next sibling parent "CrudOMatic" <crudomatic gmail.com> writes:
On Tuesday, 10 April 2012 at 08:05:33 UTC, simendsjo wrote:
 On Tue, 10 Apr 2012 09:41:28 +0200, CrudOMatic 
 <crudomatic gmail.com> wrote:

 The D documentation is a little lacking in a lot of areas. I'm 
 needing to know an exact way of making arrays of objects.

 For example:

 /* Deck class */
 	// Will be adjusted with the proper cards for each game type
 	class Deck {
 		/* Card count - used to keep track of how many cards are 
 left in the deck - when zero, Deck is discarded from the Shoe 
 */
 		int cardCount;
 		/* Cards array - initialized to cardCount elements */
 		Card cards[];
 		
 		/* Constructor */
 		this(int no_cards) {
 			cardCount = no_cards;
 			cards = new Card[cardCount];
 		}
 		
 		/* Destructor */
 		~this() {
 			delete cards;
 		}
 	}

 the cards[] array is meant to be an array of Card objects, and 
 I'm initializing it in the constructor as seen above. This 
 hasn't been tested yet, but I'm needing to know if this is the 
 correct way of doing it - to save headaches later.

 Also, while I'm here, how would you go about moving objects 
 from the cards array in the Deck class to another class 
 containing a cards array - I'm talking about MOVING them, not 
 COPYING them. I don't want any issues with references being 
 destroyed after being moved to another class when I happen to 
 destroy an instance of the Deck class.

In D, arrays includes the number of elements in the array. Card[] cards; assert(cards.length == 0); // Automatically initialized to 0 elements cards.length = cardCount; // cards gets cardCount of null elements cards.reserve(cardCount); // This just extends the array without filling with null elements. cards.length stays at 0 D includes array slices - a view into an array. This way, you can reference cards without copying them. auto other = cards[1..$-1]; // all but first and last card I'll let someone else answer the moving part as I'm not sure how that could be done. The delete statement is going away. You should use clear(cards) instead. This really isn't needed as Ds GC will take care of it eventually. Your example could be written as class Deck { Card[] cards; property int cardCount() { return cards.length; } this(int no_cards) { cards.reserve(no_cards); } } Arrays are more complicated than they seem at first. I recommend you read this article: http://dlang.org/d-array-article.html D has a newsgroup, .learn, for beginner questions.

Thanks, I'm not sure if this is what I was after though. Let me explain a little more, and you can tell me if I'm stupid or not. To make it simple - I have 4 (well more than 4, but trying to get these shored up first) classes, Shoe, Deck, Hand and Card. The Shoe class contains anywhere from 4 to 8 Deck objects in a Deck array. The Deck class contains anywhere from 40 to 54 Card objects in a Card array. The Hand class contains a 2-dimensional array of Card Objects ([2][]), that are to be moved from the Deck array and placed here. The Card class just contains info on the card in question. The cardCount property in Deck gets decremented each time a card is dealt from it, until it reaches zero - which then that instance of the Deck object is removed from the Deck array in Shoe - thus why I needed to move instead of just copying or referencing. The way I'm understanding your solution is that you are treating it just as a normal property instead of a generic object reference count. If not, then I've mistaken what you were meaning. It's merely there to tell me how many objects are left until time to clear() it away.
Apr 10 2012
prev sibling next sibling parent simendsjo <simendsjo gmail.com> writes:
On Tue, 10 Apr 2012 10:53:58 +0200, CrudOMatic <crudomatic gmail.com>  
wrote:

 On Tuesday, 10 April 2012 at 08:05:33 UTC, simendsjo wrote:
 On Tue, 10 Apr 2012 09:41:28 +0200, CrudOMatic <crudomatic gmail.com>  
 wrote:

 The D documentation is a little lacking in a lot of areas. I'm needing  
 to know an exact way of making arrays of objects.

 For example:

 /* Deck class */
 	// Will be adjusted with the proper cards for each game type
 	class Deck {
 		/* Card count - used to keep track of how many cards are left in the  
 deck - when zero, Deck is discarded from the Shoe */
 		int cardCount;
 		/* Cards array - initialized to cardCount elements */
 		Card cards[];
 		
 		/* Constructor */
 		this(int no_cards) {
 			cardCount = no_cards;
 			cards = new Card[cardCount];
 		}
 		
 		/* Destructor */
 		~this() {
 			delete cards;
 		}
 	}

 the cards[] array is meant to be an array of Card objects, and I'm  
 initializing it in the constructor as seen above. This hasn't been  
 tested yet, but I'm needing to know if this is the correct way of  
 doing it - to save headaches later.

 Also, while I'm here, how would you go about moving objects from the  
 cards array in the Deck class to another class containing a cards  
 array - I'm talking about MOVING them, not COPYING them. I don't want  
 any issues with references being destroyed after being moved to  
 another class when I happen to destroy an instance of the Deck class.

In D, arrays includes the number of elements in the array. Card[] cards; assert(cards.length == 0); // Automatically initialized to 0 elements cards.length = cardCount; // cards gets cardCount of null elements cards.reserve(cardCount); // This just extends the array without filling with null elements. cards.length stays at 0 D includes array slices - a view into an array. This way, you can reference cards without copying them. auto other = cards[1..$-1]; // all but first and last card I'll let someone else answer the moving part as I'm not sure how that could be done. The delete statement is going away. You should use clear(cards) instead. This really isn't needed as Ds GC will take care of it eventually. Your example could be written as class Deck { Card[] cards; property int cardCount() { return cards.length; } this(int no_cards) { cards.reserve(no_cards); } } Arrays are more complicated than they seem at first. I recommend you read this article: http://dlang.org/d-array-article.html D has a newsgroup, .learn, for beginner questions.

Thanks, I'm not sure if this is what I was after though. Let me explain a little more, and you can tell me if I'm stupid or not. To make it simple - I have 4 (well more than 4, but trying to get these shored up first) classes, Shoe, Deck, Hand and Card. The Shoe class contains anywhere from 4 to 8 Deck objects in a Deck array. The Deck class contains anywhere from 40 to 54 Card objects in a Card array. The Hand class contains a 2-dimensional array of Card Objects ([2][]), that are to be moved from the Deck array and placed here. The Card class just contains info on the card in question. The cardCount property in Deck gets decremented each time a card is dealt from it, until it reaches zero - which then that instance of the Deck object is removed from the Deck array in Shoe - thus why I needed to move instead of just copying or referencing. The way I'm understanding your solution is that you are treating it just as a normal property instead of a generic object reference count. If not, then I've mistaken what you were meaning. It's merely there to tell me how many objects are left until time to clear() it away.

Not quite sure where you are going with this.. class Deck { Card popBack() { auto card = cards.popBack(); // get last card. cards.length is decremented assumeSafeAppend(cards); // now we can add cards to the deck without it relocating - not sure if you need this though return card; } } I don't know why you cannot just use a reference. When you stop using a Deck, the cards won't be cleaned by the GC as you are referencing Cards from other parts of the program - like Hand.
Apr 10 2012
prev sibling next sibling parent "CrudOMatic" <crudomatic gmail.com> writes:
On Tuesday, 10 April 2012 at 09:15:13 UTC, simendsjo wrote:
 On Tue, 10 Apr 2012 10:53:58 +0200, CrudOMatic 
 <crudomatic gmail.com> wrote:

 On Tuesday, 10 April 2012 at 08:05:33 UTC, simendsjo wrote:
 On Tue, 10 Apr 2012 09:41:28 +0200, CrudOMatic 
 <crudomatic gmail.com> wrote:

 The D documentation is a little lacking in a lot of areas. 
 I'm needing to know an exact way of making arrays of objects.

 For example:

 /* Deck class */
 	// Will be adjusted with the proper cards for each game type
 	class Deck {
 		/* Card count - used to keep track of how many cards are 
 left in the deck - when zero, Deck is discarded from the 
 Shoe */
 		int cardCount;
 		/* Cards array - initialized to cardCount elements */
 		Card cards[];
 		
 		/* Constructor */
 		this(int no_cards) {
 			cardCount = no_cards;
 			cards = new Card[cardCount];
 		}
 		
 		/* Destructor */
 		~this() {
 			delete cards;
 		}
 	}

 the cards[] array is meant to be an array of Card objects, 
 and I'm initializing it in the constructor as seen above. 
 This hasn't been tested yet, but I'm needing to know if this 
 is the correct way of doing it - to save headaches later.

 Also, while I'm here, how would you go about moving objects 
 from the cards array in the Deck class to another class 
 containing a cards array - I'm talking about MOVING them, 
 not COPYING them. I don't want any issues with references 
 being destroyed after being moved to another class when I 
 happen to destroy an instance of the Deck class.

In D, arrays includes the number of elements in the array. Card[] cards; assert(cards.length == 0); // Automatically initialized to 0 elements cards.length = cardCount; // cards gets cardCount of null elements cards.reserve(cardCount); // This just extends the array without filling with null elements. cards.length stays at 0 D includes array slices - a view into an array. This way, you can reference cards without copying them. auto other = cards[1..$-1]; // all but first and last card I'll let someone else answer the moving part as I'm not sure how that could be done. The delete statement is going away. You should use clear(cards) instead. This really isn't needed as Ds GC will take care of it eventually. Your example could be written as class Deck { Card[] cards; property int cardCount() { return cards.length; } this(int no_cards) { cards.reserve(no_cards); } } Arrays are more complicated than they seem at first. I recommend you read this article: http://dlang.org/d-array-article.html D has a newsgroup, .learn, for beginner questions.

Thanks, I'm not sure if this is what I was after though. Let me explain a little more, and you can tell me if I'm stupid or not. To make it simple - I have 4 (well more than 4, but trying to get these shored up first) classes, Shoe, Deck, Hand and Card. The Shoe class contains anywhere from 4 to 8 Deck objects in a Deck array. The Deck class contains anywhere from 40 to 54 Card objects in a Card array. The Hand class contains a 2-dimensional array of Card Objects ([2][]), that are to be moved from the Deck array and placed here. The Card class just contains info on the card in question. The cardCount property in Deck gets decremented each time a card is dealt from it, until it reaches zero - which then that instance of the Deck object is removed from the Deck array in Shoe - thus why I needed to move instead of just copying or referencing. The way I'm understanding your solution is that you are treating it just as a normal property instead of a generic object reference count. If not, then I've mistaken what you were meaning. It's merely there to tell me how many objects are left until time to clear() it away.

Not quite sure where you are going with this.. class Deck { Card popBack() { auto card = cards.popBack(); // get last card. cards.length is decremented assumeSafeAppend(cards); // now we can add cards to the deck without it relocating - not sure if you need this though return card; } } I don't know why you cannot just use a reference. When you stop using a Deck, the cards won't be cleaned by the GC as you are referencing Cards from other parts of the program - like Hand.

hmmmm... so no need for a generic object reference counter. Nice. I was trying to approach it from a literal sense (e.g. card moves from deck to player's hand) - when you do the popBack() is that object returned and deleted from the original array, or just the reference returned and ref removed from original array? The whole thing is supposed to be a large 21 simulator - everything from 21, to blackjack, to Spanish 21 to Ventiuna. I was trying to use literal real-world ideas of objects, and was wanting the moving so I didn't have weird issues later down the road, like not knowing why a reference was hanging around. I understand D has a GC, but sometimes it pays to do management yourself.
Apr 10 2012
prev sibling next sibling parent simendsjo <simendsjo gmail.com> writes:
On Tue, 10 Apr 2012 11:27:19 +0200, CrudOMatic <crudomatic gmail.com>  
wrote:
 hmmmm... so no need for a generic object reference counter. Nice. I was  
 trying to approach it from a literal sense (e.g. card moves from deck to  
 player's hand) - when you do the popBack() is that object returned and  
 deleted from the original array, or just the reference returned and ref  
 removed from original array?

The reference is returned, and it's still in the array - kind of... Say: cards is [Card1, Card2] cards.popBack(); cards is now [Card1], but Card2's reference is still there in position 2. The length of the array in decremented. If you try to append a card to cards, the runtime will see you're trying to write over the reference for Card2, so it will create a new array to avoid this. If you use assumeSafeAppend, you say that you don't mind overwriting this reference. Remember that as long as you hold a reference to Card2 somewhere, the GC won't delete the instance even if the reference no longer exists in the cards array.
 I was trying to use literal real-world ideas of objects, and was wanting  
 the moving so I didn't have weird issues later down the road, like not  
 knowing why a reference was hanging around. I understand D has a GC, but  
 sometimes it pays to do management yourself.

A card game doesn't sound like heavy use of the GC, so I don't think that should be a problem.
Apr 10 2012
prev sibling next sibling parent "CrudOMatic" <crudomatic gmail.com> writes:
On Tuesday, 10 April 2012 at 09:52:45 UTC, simendsjo wrote:
 On Tue, 10 Apr 2012 11:27:19 +0200, CrudOMatic 
 <crudomatic gmail.com> wrote:
 hmmmm... so no need for a generic object reference counter. 
 Nice. I was trying to approach it from a literal sense (e.g. 
 card moves from deck to player's hand) - when you do the 
 popBack() is that object returned and deleted from the 
 original array, or just the reference returned and ref removed 
 from original array?

The reference is returned, and it's still in the array - kind of... Say: cards is [Card1, Card2] cards.popBack(); cards is now [Card1], but Card2's reference is still there in position 2. The length of the array in decremented. If you try to append a card to cards, the runtime will see you're trying to write over the reference for Card2, so it will create a new array to avoid this. If you use assumeSafeAppend, you say that you don't mind overwriting this reference. Remember that as long as you hold a reference to Card2 somewhere, the GC won't delete the instance even if the reference no longer exists in the cards array.
 I was trying to use literal real-world ideas of objects, and 
 was wanting the moving so I didn't have weird issues later 
 down the road, like not knowing why a reference was hanging 
 around. I understand D has a GC, but sometimes it pays to do 
 management yourself.

A card game doesn't sound like heavy use of the GC, so I don't think that should be a problem.

Awesome. One last question, does popFront() have the same effect of decreasing length - or should I avoid popFront()?
Apr 10 2012
prev sibling next sibling parent simendsjo <simendsjo gmail.com> writes:
On Tue, 10 Apr 2012 12:01:10 +0200, CrudOMatic <crudomatic gmail.com>  
wrote:

 Awesome. One last question, does popFront() have the same effect of  
 decreasing length - or should I avoid popFront()?

popFront will also reduce the length, but it will slice away the first item. Read the article I linked earlier. This means that if you append to the array, the array will keep expanding and eventually relocate as you cannot reuse the front of the array without doing some manual work. It sounds to me like you want popBack and assumeSafeAppend. This is basically what popBack and popFront from std.array looks like: void popBack(A)(ref A a) { a = a[0 .. $ - 1]; // $ is a.length } void popFront(A)(ref A a) { a = a[1 .. $]; }
Apr 10 2012
prev sibling next sibling parent "CrudOMatic" <crudomatic gmail.com> writes:
Thanks much.
Apr 10 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 10 Apr 2012 03:41:28 -0400, CrudOMatic <crudomatic gmail.com>  
wrote:

 The D documentation is a little lacking in a lot of areas. I'm needing  
 to know an exact way of making arrays of objects.

 For example:

 /* Deck class */
 	// Will be adjusted with the proper cards for each game type
 	class Deck {
 		/* Card count - used to keep track of how many cards are left in the  
 deck - when zero, Deck is discarded from the Shoe */
 		int cardCount;
 		/* Cards array - initialized to cardCount elements */
 		Card cards[];
 		
 		/* Constructor */
 		this(int no_cards) {
 			cardCount = no_cards;
 			cards = new Card[cardCount];
 		}
 		
 		/* Destructor */
 		~this() {
 			delete cards;
 		}
 	}

I want to stop you right there. *DON'T* use a destructor here, you will have issues, mostly of the random segfault nature. Quickly explained, if the Deck class and it's cards array are destroyed at the same time in the GC, there is no guarantee that the cards array is valid when you try to destroy it. Destructors are strictly for cleaning up resources that *AREN'T* allocated by the GC. For example anything created with C's malloc, or an open file descriptor, etc.
 the cards[] array is meant to be an array of Card objects, and I'm  
 initializing it in the constructor as seen above. This hasn't been  
 tested yet, but I'm needing to know if this is the correct way of doing  
 it - to save headaches later.

This is fine. Note that D slices (what cards[] is) contain a length member, so no need to store an extra member.
 Also, while I'm here, how would you go about moving objects from the  
 cards array in the Deck class to another class containing a cards array  
 - I'm talking about MOVING them, not COPYING them. I don't want any  
 issues with references being destroyed after being moved to another  
 class when I happen to destroy an instance of the Deck class.

All classes are references (i.e. an element of cards is a single pointer to a Card instance). There is no need to move them, as a straight copy is just copying the reference. And since you have removed the dtor, there should be no worry about accidentally destroying the cards ;) You really should read the spec page on classes (http://dlang.org/class.html) and I highly recommend picking up the D programming language book. -Steve
Apr 10 2012
prev sibling next sibling parent "CrudOMatic" <crudomatic gmail.com> writes:
Sorry, but a small issue.

the line: auto card = cards.popBack();

throws the errors:

error: variable xxx.card voids have no value
error: expression popBack(this.cards) is void and has no value

I tried reserving the space, I even tried cards = new 
Card[no_cards];
Apr 10 2012
prev sibling next sibling parent simendsjo <simendsjo gmail.com> writes:
On Tue, 10 Apr 2012 13:58:44 +0200, CrudOMatic <crudomatic gmail.com>  
wrote:

 Sorry, but a small issue.

 the line: auto card = cards.popBack();

 throws the errors:

 error: variable xxx.card voids have no value
 error: expression popBack(this.cards) is void and has no value

 I tried reserving the space, I even tried cards = new Card[no_cards];

Sorry, popBack returns void. You have to get the back of the array before calling popBack(). Here's an example: import std.array; class Card {} void main() { Card[] cards; cards.reserve(1024); assert(cards.capacity >= 1024); assert(cards.length == 0); // still 0 cards ~= new Card(); // add a Card assert(cards.length == 1); auto card = cards.back; // get last element cards.popBack(); // remove last element assert(card); // non-null assert(cards.length == 0); // "empty" again assumeSafeAppend(cards); // allow us to append to it without reallocating auto oldptr = cards.ptr; cards ~= new Card(); assert(cards.length == 1); assert(card); // card still alive and kicking assert(cards.ptr == oldptr); // and no reallocation }
Apr 10 2012
prev sibling next sibling parent "CrudOMatic" <crudomatic gmail.com> writes:
Thanks, works fine now.
Apr 10 2012
prev sibling next sibling parent "Jesse Phillips" <Jessekphillips+D gmail.com> writes:
 class Deck {
   Card popBack() {
     auto card = cards.popBack(); // get last card. cards.length

Note that popBack() is void: http://dlang.org/phobos/std_array.html#popBack use auto card = cards.back(); cards.popBack();
Apr 10 2012
prev sibling next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Tue, 10 Apr 2012 07:35:31 -0400
schrieb "Steven Schveighoffer" <schveiguy yahoo.com>:

 Destructors are strictly for cleaning up resources that *AREN'T* allocated  
 by the GC.  For example anything created with C's malloc, or an open file  
 descriptor, etc.

This I think is a very good advice to beginners. Short and precise. It is much more fun to use a new language when you can also free your mind from some archaic concepts now and then :) -- Marco
Apr 10 2012
prev sibling next sibling parent "CrudOMatic" <crudomatic gmail.com> writes:
On Tuesday, 10 April 2012 at 18:28:39 UTC, Marco Leise wrote:
 Am Tue, 10 Apr 2012 07:35:31 -0400
 schrieb "Steven Schveighoffer" <schveiguy yahoo.com>:

 Destructors are strictly for cleaning up resources that 
 *AREN'T* allocated  by the GC.  For example anything created 
 with C's malloc, or an open file  descriptor, etc.

This I think is a very good advice to beginners. Short and precise. It is much more fun to use a new language when you can also free your mind from some archaic concepts now and then :)

That's good to know. Just looking over more of the docs.
Apr 11 2012
prev sibling next sibling parent Johannes Pfau <nospam example.com> writes:
Am Tue, 10 Apr 2012 20:28:28 +0200
schrieb Marco Leise <Marco.Leise gmx.de>:

 Am Tue, 10 Apr 2012 07:35:31 -0400
 schrieb "Steven Schveighoffer" <schveiguy yahoo.com>:
 
 Destructors are strictly for cleaning up resources that *AREN'T*
 allocated by the GC.  For example anything created with C's malloc,
 or an open file descriptor, etc.

This I think is a very good advice to beginners. Short and precise. It is much more fun to use a new language when you can also free your mind from some archaic concepts now and then :)

That's a dangerous advice though: You can create lots of file descriptors without allocating much memory. So in the worst case you run out of file-descriptors long before the GC calls your destructor.
Apr 11 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Apr 11, 2012 at 07:07:54PM +0200, Johannes Pfau wrote:
 Am Tue, 10 Apr 2012 20:28:28 +0200
 schrieb Marco Leise <Marco.Leise gmx.de>:
 
 Am Tue, 10 Apr 2012 07:35:31 -0400
 schrieb "Steven Schveighoffer" <schveiguy yahoo.com>:
 
 Destructors are strictly for cleaning up resources that *AREN'T*
 allocated by the GC.  For example anything created with C's
 malloc, or an open file descriptor, etc.

This I think is a very good advice to beginners. Short and precise. It is much more fun to use a new language when you can also free your mind from some archaic concepts now and then :)

That's a dangerous advice though: You can create lots of file descriptors without allocating much memory. So in the worst case you run out of file-descriptors long before the GC calls your destructor.

Yeah, one should not rely on the GC to destroy objects at a given time, since it can be arbitrarily distant in the future. For releasing resources, what really should be used are scope statements: auto myResource = acquireResource; scope(exit) myResource.release(); T -- Windows 95 was a joke, and Windows 98 was the punchline.
Apr 11 2012
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 11 Apr 2012 13:07:54 -0400, Johannes Pfau <nospam example.com>  
wrote:

 Am Tue, 10 Apr 2012 20:28:28 +0200
 schrieb Marco Leise <Marco.Leise gmx.de>:

 Am Tue, 10 Apr 2012 07:35:31 -0400
 schrieb "Steven Schveighoffer" <schveiguy yahoo.com>:

 Destructors are strictly for cleaning up resources that *AREN'T*
 allocated by the GC.  For example anything created with C's malloc,
 or an open file descriptor, etc.

This I think is a very good advice to beginners. Short and precise. It is much more fun to use a new language when you can also free your mind from some archaic concepts now and then :)

That's a dangerous advice though: You can create lots of file descriptors without allocating much memory. So in the worst case you run out of file-descriptors long before the GC calls your destructor.

This is not "dangerous" advice. Freeing resources you own that are not yet freed is perfectly acceptable, and IMO, good practice. If you own a resource, and it's not closed manually, you have an obligation to free it. If you create a class that owns a file descriptor, and don't close it in the destructor, then it leaves the possibility that you have destroyed all references to the file descriptor, but left it open, thereby leaking it. Yes, it is advisable that when you are creating unlimited numbers of file-descriptor owning classes, that you manually close them. But the destructor is a perfectly good place to do that. I once wrote an application that relied on the GC to close file descriptors, and it never ran out of file descriptors. -Steve
Apr 11 2012