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