Classes or stucts :: Newbie
Jonathan M Davis
jmdavisProg at gmx.com
Sun Dec 19 13:23:42 PST 2010
On Monday 20 December 2010 07:00:31 David Currie wrote:
> I am new to D (like many have done C++ , Java ).
>
> Can a class be instantiated on the stack ?
>
> eg
>
> class C
> {
> private int _I1;
> private int _I2;
>
> public:
>
> this(int pI) // constructor
> {
> _I1 = pI;
> _I2 = pI + 1;
> }
>
> // ... other methods etc
> }
>
> void f() // just a function
> {
>
> C myC(3); // C++ syntax BUT is there a d equivalent
>
> }
>
> It appears that D ASSUMES myC is really a myC*(in C++)
>
> and therefore requires
>
> C myC = new C(3);
> // but this ALWAYS requires calling the memory allocator
> // this is what Java does (forces your Class instance onto the Heap)
>
> Is there any way in D to instantiate a stack object ?
>
> Will a struct do?
Structs are value types. Therefore, they go on the stack unless you have a
pointer to them.
struct Foo {}
Foo a; //on stack
Foo* b = new Foo(); //on heap
Classes are reference types. The are therefore always on the heap. It's like
what you get in Java.
class Bar {}
Bar a; //On the heap.
Structs do not have inheritance (and thus don't have polymorphism), but they can
be used for RAII. Assigning one to another means copying it (or moving it if the
compiler determines that it can). Because struct member functions are not
virtual, they often can be inlined.
Classes do have inheritance (and thus do have polymorphism), but they can't use
RAII. Assigning one to another means assigning a reference. Both references now
refer to the same object. You'll have to use a clone method of some kind to get
an actualy, deep copy. Because class member functions are almost always virtual,
it's much rarer that they can be inlined.
The language did have scoped classes, which put the class itself on the stack
instead of the heap:
class Bar {}
scope Bar a; //On the stack.
But it's inherently unsafe, so it's being removed from the language. There will
be a library solution to do it, but again, it's unsafe. If you were to pass a
scaped class to any other function, you risk the reference escaping, and then
you'll end up with a reference to an object that doesn't exist once the function
that declared it exits.
Classes are meant to be on the heap. structs are meant to be on the stack but
can be on the heap. Generally-speaking, if you use a class if you need a
reference type or need polymorphism. Otherwise, you use a struct (reasons for
using one or the other can, of course, get more complicated that that, but
that's the core of it).
Allowing classes on the like C++ does allows for problems like sheering and
disallows polymorphism. D opted to split the concept into two different types of
types: classes and structs.
The language which is closest to D with regards to structs and classes that I'm
aware of is C#, though I believe that D structs are definitely more powerful than
C# structs. In D, you just don't use classes as often as you'd do in Java or
C++, because structs in D do a lot of what classes do in those languages. For
any user-defined type, you need to decide whether a struct or a class is more
appropriate for what you're trying to do. The approach has definite benefits, but
it does take some getting used to.
> Does a struct have a constructor (as opposed to an opcall?)
structs can have constructs just like classes - they just can't have default
constructors. The reason for this is that all types in D have an init property
that variables of that type are initialized to when they are default
initialized. For integral types, it's 0; for bool, it's false; for references
and pointers it's null; etc. For structs, it's what the member variables are
directly initialized to. init precludes having an arbitrary constructor, because
init must be determinable at compile time, can't have exceptions being thrown,
etc. We may get some sort of limited default constructor for structs at some
point, but it's not at all straightforward to have one, so we don't. The
solution then, if you need one, is to use a static opCall() function, and then
do
Foo a = Foo(); //calls static opCall().
instead of
Foo a; //Just uses Foo.init.
So, structs _do_ have constructors, just not default constructors.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list