D - dynamic array of objects
- Mark Brudnak (23/23) Dec 09 2003 Help!
- Charles Sanders (27/50) Dec 09 2003 You have not allocated space for
- Mark Brudnak (6/66) Dec 09 2003 How is what I am doing different than:
- Vathix (7/11) Dec 09 2003 Length"?
- Mark Brudnak (40/44) Dec 10 2003 Ok. So for built in types...
- Brad Beveridge (10/79) lid Date I think that this would get too confusing. The semantics at the moment
- Sean L. Palmer (120/195) Dec 10 2003 Not really. Since they're always by reference anyway, how could it make...
- Mark Brudnak (77/118) Dec 11 2003 its
- Ian Johnston (17/22) Dec 12 2003 Hmmm, it's not clear to me that this is so. What if I want a reference t...
- Sean L. Palmer (10/34) Dec 12 2003 Did you even read the rest of the post?
- Robert (40/116) Dec 11 2003 I've seen *many* C++ programmers who suffer from the explicit constructi...
- Antti =?iso-8859-1?Q?Syk=E4ri?= (24/35) Dec 10 2003 Value objects (structs, enums, built-in objects, function pointers,
- Felix (5/52) Dec 10 2003 I agree that heap/stack distinction is useful for some optimizations. As...
- J Anderson (12/91) Dec 11 2003 For template object creation, it would be nice if there was one uniform
- Patrick Down (9/60) Dec 09 2003 myBar.manyFoos[0] = new Foo;
Help! This code builds but does not run. It crashes on the indicated line. What am I doing wrong? import std.stream ; import std.conv ; import std.string ; class Foo { float x ; float y ; } ; class Bar { float step ; Foo[] manyFoos ; } ; int main(char[][] args) { Bar myBar = new Bar ; myBar.manyFoos.length = 3 ; printf("I am here\n") ; myBar.manyFoos[0].x = 0.0f ; // Crash: "Error: Access Violation" printf("Now I am here\n") ; return 0 ; }
Dec 09 2003
You have not allocated space for myBar.manyFoos[0] import std.stream ; import std.conv ; import std.string ; class Foo { float x ; float y ; } ; class Bar { float step ; Foo[] manyFoos ; } ; int main(char[][] args) { Bar myBar = new Bar ; myBar.manyFoos.length = 3 ; printf("I am here\n") ; myBar.manyFoos[0] = new Foo; myBar.manyFoos[0].x = 0.0f ; // no crash printf("Now I am here\n") ; return 0 ; } works as expected "Mark Brudnak" <malibrud provide.net> wrote in message news:br64bc$1r6t$1 digitaldaemon.com...Help! This code builds but does not run. It crashes on the indicated line.Whatam I doing wrong? import std.stream ; import std.conv ; import std.string ; class Foo { float x ; float y ; } ; class Bar { float step ; Foo[] manyFoos ; } ; int main(char[][] args) { Bar myBar = new Bar ; myBar.manyFoos.length = 3 ; printf("I am here\n") ; myBar.manyFoos[0].x = 0.0f ; // Crash: "Error: Access Violation" printf("Now I am here\n") ; return 0 ; }
Dec 09 2003
How is what I am doing different than: int[] array; array.length = 100; Which is taken from the D spec under Arrays->"Setting Dynamic Array Length"? "Charles Sanders" <sanders-consulting comcast.net> wrote in message news:br64j3$1reu$1 digitaldaemon.com...You have not allocated space for myBar.manyFoos[0] import std.stream ; import std.conv ; import std.string ; class Foo { float x ; float y ; } ; class Bar { float step ; Foo[] manyFoos ; } ; int main(char[][] args) { Bar myBar = new Bar ; myBar.manyFoos.length = 3 ; printf("I am here\n") ; myBar.manyFoos[0] = new Foo; myBar.manyFoos[0].x = 0.0f ; // no crash printf("Now I am here\n") ; return 0 ; } works as expected "Mark Brudnak" <malibrud provide.net> wrote in message news:br64bc$1r6t$1 digitaldaemon.com...Help! This code builds but does not run. It crashes on the indicated line.Whatam I doing wrong? import std.stream ; import std.conv ; import std.string ; class Foo { float x ; float y ; } ; class Bar { float step ; Foo[] manyFoos ; } ; int main(char[][] args) { Bar myBar = new Bar ; myBar.manyFoos.length = 3 ; printf("I am here\n") ; myBar.manyFoos[0].x = 0.0f ; // Crash: "Error: Access Violation" printf("Now I am here\n") ; return 0 ; }
Dec 09 2003
"Mark Brudnak" <malibrud provide.net> wrote in message news:br6581$1sbi$1 digitaldaemon.com...How is what I am doing different than: int[] array; array.length = 100; Which is taken from the D spec under Arrays->"Setting Dynamic ArrayLength"?Classes are different from other types because they use references. If you set the length of an array of classes, you're allocating more references, not class objects themselves. You should loop through the array and assign new objects.
Dec 09 2003
"Vathix" <vathix dprogramming.com> wroteClasses are different from other types because they use references. If you set the length of an array of classes, you're allocating more references, not class objects themselves. You should loop through the array and assign new objects.Ok. So for built in types... int thisArray[] ; thisArray.length = theLength ; // now I have an array of ints thisArray[anIndex] = aNumber ; But for classes... SomeClass thatArray[] ; thatArray.length = theOtherLength ; // now I have an array of uninitialized class references thatArray[anIndex] = new SomeClass ; // create something for it to reference. thatArray[anIndex].aField = aNumber ; Now my question... Why can't both have the same semantics? That is why can't classes behave like the built in types? I am sure that this issue has been discussed before and I know that the immediate answer has to do with passing objects by reference, garbage collection, reference counting etc. The issue is why do we maintain the reference/object distinction? Since a reference which is never assigned anything is meaningless and an unassigned new is equally meaningless. To my knowledge, there are only two scenarios in which a class reference is used. 1) It holds a reference to an explicitly created object ; AlphaClass alpha = new AlphaClass(p1, p2) ; // create a new object to be held by alpha alpha.fieldN = x ; 2) It is assigned a reference to some pre-existing object by assignment ; BetaClass beta ; /* some code.... */ beta = lookupBeta("lastWeeksBeta") ; // reference is assigned by a lookup Now in case 1) the 'new' should be implicit. That is, I should be able to write... AlphaClass alpha(p1, p2) ; alpha.fieldN = x ; // execute alpha = new AlphaClass(p1, p2) implicitly And the compiler knows to create a new AlphaClass object and assign it to alpha. In this way both garbage collection and garbage creation would be implicit. Right now garbage creation is explicit (via new) and garbage collection is implicit. P.S. garbage creation is probably not the right term. When an object is new it is not garbage.
Dec 10 2003
I think that this would get too confusing. The semantics at the moment are: all objects are references. The only way to create an object is with new. I like explicitly creating an object. Implicit object creation (example, passing objects via the stack in C++) is a hassle, and you need to be careful not to end up passing huge structures when a reference would do. I think with your suggestion objects would end up being created at unexpected times. Brad Mark Brudnak wrote:"Vathix" <vathix dprogramming.com> wroteClasses are different from other types because they use references. If you set the length of an array of classes, you're allocating more references, not class objects themselves. You should loop through the array and assign new objects.Ok. So for built in types... int thisArray[] ; thisArray.length = theLength ; // now I have an array of ints thisArray[anIndex] = aNumber ; But for classes... SomeClass thatArray[] ; thatArray.length = theOtherLength ; // now I have an array of uninitialized class references thatArray[anIndex] = new SomeClass ; // create something for it to reference. thatArray[anIndex].aField = aNumber ; Now my question... Why can't both have the same semantics? That is why can't classes behave like the built in types? I am sure that this issue has been discussed before and I know that the immediate answer has to do with passing objects by reference, garbage collection, reference counting etc. The issue is why do we maintain the reference/object distinction? Since a reference which is never assigned anything is meaningless and an unassigned new is equally meaningless. To my knowledge, there are only two scenarios in which a class reference is used. 1) It holds a reference to an explicitly created object ; AlphaClass alpha = new AlphaClass(p1, p2) ; // create a new object to be held by alpha alpha.fieldN = x ; 2) It is assigned a reference to some pre-existing object by assignment ; BetaClass beta ; /* some code.... */ beta = lookupBeta("lastWeeksBeta") ; // reference is assigned by a lookup Now in case 1) the 'new' should be implicit. That is, I should be able to write... AlphaClass alpha(p1, p2) ; alpha.fieldN = x ; // execute alpha = new AlphaClass(p1, p2) implicitly And the compiler knows to create a new AlphaClass object and assign it to alpha. In this way both garbage collection and garbage creation would be implicit. Right now garbage creation is explicit (via new) and garbage collection is implicit. P.S. garbage creation is probably not the right term. When an object is new it is not garbage.
lid Date
Not really. Since they're always by reference anyway, how could it make any new objects... there's no "copy constructor" to accidentally get called. D also doesn't have implicit user-defined conversions. He wasn't saying he wanted stack storage, only that allocation from the heap should be automatic and implicit. By saying A a; you are telling the compiler to make a new object of class a by calling its "default" constructor (I guess also by calling new!) and simultaneously creating the reference A to hold a reference to said object. If you ask me I think it should be the object's responsibility where it gets allocated and deallocated from. More than the user of the objects. Actually the best place for responsibility for creation of objects should be in the various Container classes. You then cannot have an object unless you get it from some container, and all containers have their allocators parameterized so that they can be replaced if necessary. Put some "Heap" memory allocator class in the standard library. Give it an area of memory and it can manage it. Then you can create new heap regions and install Heap managers for them, and install Containers in your heaps, from which you allocate other Objects (maybe more Containers). But how could you always query containers for the storage, while also passing the list of parameters to the ctor of the newly allocated object, in the same call? You don't want to have the object uninitialized. Heck we probably don't want references to be uninitialized, and don't allow them to be null either. So have to group allocation with initialization, as a unit. It's convenient anyway. Unfortunately it's not that simple. We also want to be able to override where an object comes from, otherwise may as well just let each object decide where it comes from, and have to basically derive from a class and override the allocation to change it, or do typecasting yourself, like C++. It seems natural to group allocation and initialization. And as mentioned earlier what would you do with a newly allocated reference unless you're going to store it directly into a variable? Increment it? No. Give it commands? That's a lot to pack together syntactically. You either put it in an existing variable via assignment, or you initialize a newly created reference to hold the new object, with the pattern: class A { } A a = new A; or sometimes A a; a = new A; and the thing that actually does get a lot of newbie questions here on this NG and is in the FAQ, A a; // newbie expects he actually has a live A object instance stored in a, but really by current rules it's null. I almost agree with the newbie, that the end result of the declaration should be a live object. But apparently people find this null reference idea useful, so to allow those null references to be created, you should allow a syntax to do so... currently that's "A a;" So let's leave that one alone and add this one: A a(); // initialize a with new a allocated with default new and initialized using the default constructor This is precisely equivalent to: A a = new A; // the final empty () to call the default ctor elided You can add other parameters to call a different constructor: A a(parm1,p2); // same as A a = new A(parm1,p2); Only I really do want objects to come from containers (such as Heap, which would be nice if it could create any kind of object) So I'd want to somehow get the object from the container, whilst simultaneously supplying its constructor with parameters. A a = myheap.A(); This reminds me a bit of C++'s user-defined conversion function, which in fact could potentially, now that I think about it, as a way to "create" objects of a given type 'from' some other object. I used to come across the idea frequently that creation should be thought of as a conversion from void to some other object type. But maybe a cast from the container type to the containee type would be an allocation. Obviously you would want to be able to override this. And also it makes sense that you would want to be able to convert to (allocate) more than one type (think Heap) and this is precisely what C++'s user defined conversion operators do. They give the object the opportunity to allocate, initialize, and return a new object. But C++'s stop at copy constructor semantics (no parameters, new object is either another representation of the called object, or needs no parameters in order to be constructed). If you want to pass parameters to the new object you have to make a function, which has different syntax. Maybe property syntax could be unified with the "new" operator (or object!) extern Heap new; extern MyObj foo,bar; A a = new.A(foo); You could also allocate derived classes. Something that wouldn't be possible with "A a(x);" syntax. You could even pass commands to the new object (thru it's new variable, in case it matters) by continuing the property chain: A a = new.A(foo).DoTask1().DoTask2(bar).DoTask3(); But not sure what you could do with the results of such functions. Maybe that's going too far. Whaddya think? Maybe C/C++ got allocation responsibility wrong and it should reside with the container. Thus the complexity of C++ operator new and delete overloading. Those are overloaded on the type of the object itself. Unfortunately those control creation everywhere, not just in one region of the program, have to deal with the possibility of being overridden in derived classes, have to deal with allocating derived classes, so size must be a parameter, then how to allocate arrays, and so on, and so forth. It wouldn't be so bad, deriving from a class and overriding some things, if it weren't such a hassle to do generically (you have to insert shims to patch thru constructor calls and certain other operations, which you may not know the exact variations of if you are a template.) The new STL allocators are nicer, but are pretty complicated. I don't know anybody who really uses them. Allocation shouldn't be all that complicated. Sean "Brad Beveridge" <brad clear.net.nz> wrote in message news:br9069$6oi$1 digitaldaemon.com...I think that this would get too confusing. The semantics at the moment are: all objects are references. The only way to create an object is with new. I like explicitly creating an object. Implicit object creation (example, passing objects via the stack in C++) is a hassle, and you need to be careful not to end up passing huge structures when a reference would do. I think with your suggestion objects would end up being created at unexpected times. Brad Mark Brudnak wrote:you"Vathix" <vathix dprogramming.com> wroteClasses are different from other types because they use references. Ifreferences,set the length of an array of classes, you're allocating moreassignnot class objects themselves. You should loop through the array andbehavenew objects.Ok. So for built in types... int thisArray[] ; thisArray.length = theLength ; // now I have an array of ints thisArray[anIndex] = aNumber ; But for classes... SomeClass thatArray[] ; thatArray.length = theOtherLength ; // now I have an array of uninitialized class references thatArray[anIndex] = new SomeClass ; // create something for it to reference. thatArray[anIndex].aField = aNumber ; Now my question... Why can't both have the same semantics? That is why can't classesobjectslike the built in types? I am sure that this issue has been discussed before and I know that the immediate answer has to do with passingaby reference, garbage collection, reference counting etc. The issue is why do we maintain the reference/object distinction? Sinceunassignedreference which is never assigned anything is meaningless and anscenariosnew is equally meaningless. To my knowledge, there are only two;in which a class reference is used. 1) It holds a reference to an explicitly created object ; AlphaClass alpha = new AlphaClass(p1, p2) ; // create a new object to be held by alpha alpha.fieldN = x ; 2) It is assigned a reference to some pre-existing object by assignmentlookupBetaClass beta ; /* some code.... */ beta = lookupBeta("lastWeeksBeta") ; // reference is assigned by atoNow in case 1) the 'new' should be implicit. That is, I should be ableimplicitlywrite... AlphaClass alpha(p1, p2) ; alpha.fieldN = x ; // execute alpha = new AlphaClass(p1, p2)toAnd the compiler knows to create a new AlphaClass object and assign itimplicit.alpha. In this way both garbage collection and garbage creation would beisRight now garbage creation is explicit (via new) and garbage collectionnewimplicit. P.S. garbage creation is probably not the right term. When an object isit is not garbage.
Dec 10 2003
"Sean L. Palmer" <palmer.sean verizon.net> wrote <snip>By saying A a; you are telling the compiler to make a new object of class a by callingits"default" constructor (I guess also by calling new!) and simultaneously creating the reference A to hold a reference to said object.Yes. To add to that, why should the programmer care where memory is allocated? When I type: class A{ /*stuff */} ; A a ; I expect to be able to use 'a' whether 'A' is a builtin type, struct, or object. IMO 'new' is nothing more than malloc++ and it should not be necessary. The above example is not too apealing, because it is just as easy to type: A a = new A ; ...or better yet... A a = A.new() ; However things get ugly when object references are created by a container class, like dynamic arrays, for example A b[] ; b.length = c ; foreach(A thisb ; b){ thisb = new A} ; int oldlength = b.length ; b.length = d ; // now which values of 'b' are initialized? Which are null references? if dc i need to do something...if (d > c) { foreach(a thisb ; b[oldlength..b.length]) {thisb = new A } ; } This type of forced allocation is a fertile place for bugs to develop. It also breaks the metaphor of the dynamic arrays. That is they grow by assigning .length, and in most cases newly allocated elements are ready to use, if it is an array of class references they are not. <snip>I almost agree with the newbie, that the end result of the declaration should be a live object. But apparently people find this null reference idea useful, so to allow those null references to be created, you should allow a syntax to do so... currently that's "A a;" So let's leave thatonealone and add this one:I think that in every case I have seen, a NULL is always used as to pass boolian type information such as a flag, error indicator, special mode for a function, etc. all of which can be handled by better means than testing against NULL. A truely modern language should not return NULL to indicate an error, etc.... The only legitimate use that I can think of for NULL is for the termination of a linked list.A a(); // initialize a with new a allocated with default new and initialized using the default constructor This is precisely equivalent to: A a = new A; // the final empty () to call the default ctor elidedA a = new A ; A a =A.new() ; A a() ; A a ; These four statements are all equivalent and call the parameterless constructor. Syntactically (FWIW) I prefer the fourth, then the second. The only problem with this is that the construction is wasted if the object reference 'a' is assigned to some other preexisting object. A a ; // implicitly executes as: A a = new A ; a = lookUpObject("someString") ; // overwrite the previously allocated object.You can add other parameters to call a different constructor: A a(parm1,p2); // same as A a = new A(parm1,p2);Yes...exactly... <snip>Maybe property syntax could be unified with the "new" operator (orobject!)extern Heap new; extern MyObj foo,bar; A a = new.A(foo);A better construction is: A a = A.new(foo) ; Because this is what is happening behind the scenes. You are asking the class to instantiate an instance of itself.You could also allocate derived classes. Something that wouldn't be possible with "A a(x);" syntax. You could even pass commands to the new object (thru it's new variable, in case it matters) by continuing the property chain: A a = new.A(foo).DoTask1().DoTask2(bar).DoTask3();As long as DoTask1, DoTask2, DoTask3 all return a reference to the object. This is the convention of Smalltalk.But not sure what you could do with the results of such functions. Maybe that's going too far.The functions would have to return a reference to the class. see above.Whaddya think? Maybe C/C++ got allocation responsibility wrong and it should reside with the container. Thus the complexity of C++ operator new and delete overloading. Those are overloaded on the type of the object itself. Unfortunately those control creation everywhere, not just in one region of the program, have to deal with the possibility of beingoverriddenin derived classes, have to deal with allocating derived classes, so size must be a parameter, then how to allocate arrays, and so on, and so forth. It wouldn't be so bad, deriving from a class and overriding some things,ifit weren't such a hassle to do generically (you have to insert shims to patch thru constructor calls and certain other operations, which you maynotknow the exact variations of if you are a template.) The new STLallocatorsare nicer, but are pretty complicated. I don't know anybody who reallyusesthem. Allocation shouldn't be all that complicated.If you think about it, an object reference is already a container of sorts. It is a chunk of memory of fixed size which points to among other things the instance variables of the object, which live on the heap. One more thought, when I learned to program I did not know the difference between a stack and a heap, and I didn't need to. Thankfully the language hid those details from the programmer. Then I learned C and was exposed to the heap via the malloc() function. As history proved, programmers managing their own memory is a tremendous source of bugs. With the post C++ pushed back to the compiler and the runtime environment (at least part way). With the introduction of garbage collection object destruction has been pushed back beneath the surface of the language definition. Unfortunately, memory allocation is still a part of these languages so we still have to maintain the reference/object distinction.
Dec 11 2003
In article <br97fu$i0u$1 digitaldaemon.com>, Sean L. Palmer says... [...]By saying A a; you are telling the compiler to make a new object of class a by calling its "default" constructor (I guess also by calling new!) and simultaneously creating the reference A to hold a reference to said object.Hmmm, it's not clear to me that this is so. What if I want a reference to a base class (maybe abstract), and allow some factory to instantiate the object? I may not know what class of object I will end up with, especially if one day objects could be loaded from DLLs... And how would you declare members in a class declaration, would they always need an initialiser too? Wouldnt that be more confusing if there were different meanings for locals and class data members? class X { A a1; // declare reference, no instantiation }; void X::f() { A a2; // declare reference and instantiate }
Dec 12 2003
Did you even read the rest of the post? Sean "Ian Johnston" <Ian_member pathlink.com> wrote in message news:brcqjm$2s48$1 digitaldaemon.com...In article <br97fu$i0u$1 digitaldaemon.com>, Sean L. Palmer says... [...]itsBy saying A a; you are telling the compiler to make a new object of class a by callinga"default" constructor (I guess also by calling new!) and simultaneously creating the reference A to hold a reference to said object.Hmmm, it's not clear to me that this is so. What if I want a reference tobase class (maybe abstract), and allow some factory to instantiate theobject?I may not know what class of object I will end up with, especially if onedayobjects could be loaded from DLLs... And how would you declare members in a class declaration, would theyalwaysneed an initialiser too? Wouldnt that be more confusing if there weredifferentmeanings for locals and class data members? class X { A a1; // declare reference, no instantiation }; void X::f() { A a2; // declare reference and instantiate }
Dec 12 2003
I've seen *many* C++ programmers who suffer from the explicit construction. All of them (and me!) have written as: 1) A a; a.foo(); // Access Violation! 2) A[] a = new A[size]; a[0].foo(); // Access Violation! IMHO, it is a troublesome problem that such a code causes no errors on compiling. And, I would like implicit array construction, too. Indeed, a[i] of "A[] a = new A[size];" is a reference, I know, but I want not to initialize array elements by foreach: A[] a = new A[size]; foreach(inout elem; a) { elem = new A; } // bother! This problem is solved by template as: template anew(T) { T[] size(int size) { T[] array = new T[size]; foreach(inout elem; array) { elem = new T; } return array; } } A[] a = instance anew(A).size(size); However, I would like it to be supported by D. e.g.... // null initialization N[] n = new N[size]; // initialized by default constructor A[] a = new A[size].create(); // initialized by this(int) constructor B[] b = new B[size].create(10); // initialized index by index C[] c = new C[size].neweach(function C(int i) { return new C(i); }); This example adds no keywords and syntax. Only create and neweach methods are added to array object. In article <br9069$6oi$1 digitaldaemon.com>, Brad Beveridge says...I think that this would get too confusing. The semantics at the moment are: all objects are references. The only way to create an object is with new. I like explicitly creating an object. Implicit object creation (example, passing objects via the stack in C++) is a hassle, and you need to be careful not to end up passing huge structures when a reference would do. I think with your suggestion objects would end up being created at unexpected times. Brad Mark Brudnak wrote:Robert (Japanese)"Vathix" <vathix dprogramming.com> wroteClasses are different from other types because they use references. If you set the length of an array of classes, you're allocating more references, not class objects themselves. You should loop through the array and assign new objects.Ok. So for built in types... int thisArray[] ; thisArray.length = theLength ; // now I have an array of ints thisArray[anIndex] = aNumber ; But for classes... SomeClass thatArray[] ; thatArray.length = theOtherLength ; // now I have an array of uninitialized class references thatArray[anIndex] = new SomeClass ; // create something for it to reference. thatArray[anIndex].aField = aNumber ; Now my question... Why can't both have the same semantics? That is why can't classes behave like the built in types? I am sure that this issue has been discussed before and I know that the immediate answer has to do with passing objects by reference, garbage collection, reference counting etc. The issue is why do we maintain the reference/object distinction? Since a reference which is never assigned anything is meaningless and an unassigned new is equally meaningless. To my knowledge, there are only two scenarios in which a class reference is used. 1) It holds a reference to an explicitly created object ; AlphaClass alpha = new AlphaClass(p1, p2) ; // create a new object to be held by alpha alpha.fieldN = x ; 2) It is assigned a reference to some pre-existing object by assignment ; BetaClass beta ; /* some code.... */ beta = lookupBeta("lastWeeksBeta") ; // reference is assigned by a lookup Now in case 1) the 'new' should be implicit. That is, I should be able to write... AlphaClass alpha(p1, p2) ; alpha.fieldN = x ; // execute alpha = new AlphaClass(p1, p2) implicitly And the compiler knows to create a new AlphaClass object and assign it to alpha. In this way both garbage collection and garbage creation would be implicit. Right now garbage creation is explicit (via new) and garbage collection is implicit. P.S. garbage creation is probably not the right term. When an object is new it is not garbage.
Dec 11 2003
In article <br8sve$12k$1 digitaldaemon.com>, Mark Brudnak wrote:Why can't both have the same semantics? That is why can't classes behave like the built in types? I am sure that this issue has been discussed before and I know that the immediate answer has to do with passing objects by reference, garbage collection, reference counting etc.Value objects (structs, enums, built-in objects, function pointers, delegates and the sort) are allocated on the stack, and class objects are allocated on the heap. Stack allocation is more efficient since there's no cost of reclaiming the memory, and heap allocation has different semantics anyway. Therefore, we distinguish the two by having to use "new X" to claim memory from the heap, and leaving it out when doing it on the stack. (Don't ask me about arrays - they are somewhere in between, sometimes you must use new and sometimes not, but I haven't quite gotten the hang of it.)The issue is why do we maintain the reference/object distinction? Since a reference which is never assigned anything is meaningless and an unassigned new is equally meaningless. To my knowledge, there are only two scenarios in which a class reference is used.So null should be removed from the language? But might be handy sometimes, for example when you don't have a default constructor in the class.In this way both garbage collection and garbage creation would be implicit. Right now garbage creation is explicit (via new) and garbage collection is implicit.Still, nice thoughts. In C++ you can make a smart pointer class that automatically instantiates an object when it's created. Which might be nice sometimes, but my personal preference is to keep heap allocation explicit. Are you searching similarity between stack/heap allocated objects so that newbies would not be overwhelmed when they notice that class references are initialized to null (because they wouldn't)? They have to learn the difference between reference and value objects at some point anyway, so why not make it explicit right from the start? -Antti
Dec 10 2003
I agree that heap/stack distinction is useful for some optimizations. As for me, I do not bother about. I think it is the compiler's job where to allocate and when to instantiate an object. As for semantics/syntax, I would definetely preffer an uniform one... In article <br8sve$12k$1 digitaldaemon.com>, Mark Brudnak says..."Vathix" <vathix dprogramming.com> wroteClasses are different from other types because they use references. If you set the length of an array of classes, you're allocating more references, not class objects themselves. You should loop through the array and assign new objects.Ok. So for built in types... int thisArray[] ; thisArray.length = theLength ; // now I have an array of ints thisArray[anIndex] = aNumber ; But for classes... SomeClass thatArray[] ; thatArray.length = theOtherLength ; // now I have an array of uninitialized class references thatArray[anIndex] = new SomeClass ; // create something for it to reference. thatArray[anIndex].aField = aNumber ; Now my question... Why can't both have the same semantics? That is why can't classes behave like the built in types? I am sure that this issue has been discussed before and I know that the immediate answer has to do with passing objects by reference, garbage collection, reference counting etc. The issue is why do we maintain the reference/object distinction? Since a reference which is never assigned anything is meaningless and an unassigned new is equally meaningless. To my knowledge, there are only two scenarios in which a class reference is used. 1) It holds a reference to an explicitly created object ; AlphaClass alpha = new AlphaClass(p1, p2) ; // create a new object to be held by alpha alpha.fieldN = x ; 2) It is assigned a reference to some pre-existing object by assignment ; BetaClass beta ; /* some code.... */ beta = lookupBeta("lastWeeksBeta") ; // reference is assigned by a lookup Now in case 1) the 'new' should be implicit. That is, I should be able to write... AlphaClass alpha(p1, p2) ; alpha.fieldN = x ; // execute alpha = new AlphaClass(p1, p2) implicitly And the compiler knows to create a new AlphaClass object and assign it to alpha. In this way both garbage collection and garbage creation would be implicit. Right now garbage creation is explicit (via new) and garbage collection is implicit. P.S. garbage creation is probably not the right term. When an object is new it is not garbage.
Dec 10 2003
For template object creation, it would be nice if there was one uniform syntax (you could still keep the old ones) for object creation on the stack and heap. I suggest a new property on all types. template TCopy(T) { void new(out T newObj) { T newObj = T.new; //Creates a new int, struct, class (whatever) } } Felix wrote:I agree that heap/stack distinction is useful for some optimizations. As for me, I do not bother about. I think it is the compiler's job where to allocate and when to instantiate an object. As for semantics/syntax, I would definetely preffer an uniform one... In article <br8sve$12k$1 digitaldaemon.com>, Mark Brudnak says..."Vathix" <vathix dprogramming.com> wroteClasses are different from other types because they use references. If you set the length of an array of classes, you're allocating more references, not class objects themselves. You should loop through the array and assign new objects.Ok. So for built in types... int thisArray[] ; thisArray.length = theLength ; // now I have an array of ints thisArray[anIndex] = aNumber ; But for classes... SomeClass thatArray[] ; thatArray.length = theOtherLength ; // now I have an array of uninitialized class references thatArray[anIndex] = new SomeClass ; // create something for it to reference. thatArray[anIndex].aField = aNumber ; Now my question... Why can't both have the same semantics? That is why can't classes behave like the built in types? I am sure that this issue has been discussed before and I know that the immediate answer has to do with passing objects by reference, garbage collection, reference counting etc. The issue is why do we maintain the reference/object distinction? Since a reference which is never assigned anything is meaningless and an unassigned new is equally meaningless. To my knowledge, there are only two scenarios in which a class reference is used. 1) It holds a reference to an explicitly created object ; AlphaClass alpha = new AlphaClass(p1, p2) ; // create a new object to be held by alpha alpha.fieldN = x ; 2) It is assigned a reference to some pre-existing object by assignment ; BetaClass beta ; /* some code.... */ beta = lookupBeta("lastWeeksBeta") ; // reference is assigned by a lookup Now in case 1) the 'new' should be implicit. That is, I should be able to write... AlphaClass alpha(p1, p2) ; alpha.fieldN = x ; // execute alpha = new AlphaClass(p1, p2) implicitly And the compiler knows to create a new AlphaClass object and assign it to alpha. In this way both garbage collection and garbage creation would be implicit. Right now garbage creation is explicit (via new) and garbage collection is implicit. P.S. garbage creation is probably not the right term. When an object is new it is not garbage.
Dec 11 2003
"Mark Brudnak" <malibrud provide.net> wrote in news:br64bc$1r6t$1 digitaldaemon.com:Help! This code builds but does not run. It crashes on the indicated line. What am I doing wrong? import std.stream ; import std.conv ; import std.string ; class Foo { float x ; float y ; } ; class Bar { float step ; Foo[] manyFoos ; } ; int main(char[][] args) { Bar myBar = new Bar ; myBar.manyFoos.length = 3 ; printf("I am here\n") ;myBar.manyFoos[0] = new Foo;myBar.manyFoos[0].x = 0.0f ; // Crash: "Error: Access Violation" printf("Now I am here\n") ; return 0 ; }Alternately: struct Foo { float x ; float y ; };class Bar { float step ; Foo[] manyFoos ; } ; int main(char[][] args) { Bar myBar = new Bar ; myBar.manyFoos.length = 3 ; printf("I am here\n") ; myBar.manyFoos[0].x = 0.0f ; // Crash: "Error: Access Violation" printf("Now I am here\n") ; return 0 ; }
Dec 09 2003