Great responses, everyone. I'll try to address all of them.

Mike, I know the rules. I was asking, "Why is it this way? Why was it designed this way? What bad thing happens the other way?" When I think about most things in D, I can at least think of a reason, even if I don't agree with it. But not putting class objects on the stack makes no sense to me (assuming we still pass by reference.) Reasons below.

Ola, your response is very interesting. I would say that assignment isn't any more or less of an issue, as long as you pass by reference:

// Using C syntax to make intent clear.
class Foo { int x; }
class Bar: Foo { int y; }

void func1(Bar* bar) {
  bar.y = 4; // boom
}

void func2(Bar* bar) {
  Foo* foo = bar;
  foo.x = 3; // this is fine

  foo = new Foo;
  func1(cast(Bar*)(foo)); // uh oh
}

Illuminating comment about the ABI.

Ali, I've never liked the distinction between 'struct' and 'class' in C++ either, but that's no reason to actually make them different. It's a reason to remove 'class' and save the keyword.

re: pass-by-reference and performance, agreed, this is why we pass integers in registers. But a struct on the stack is just as fast to access locally through a pointer register - "[bp+6]" - as remotely, yes?

Finally, 'scope' is nice but it doesn't solve the segfault issue.

HS Teoh: See above for my responses about assignment and 'scope'.

bauss: "But that's not entirely true as you can allocate a struct on the heap as well."

forkit: "where they live in memory should be less of the programmers concern, and more an implementation issue (although some programmers will of course consider this as well)."

Precisely. You can allocate structs, and you can put class objects in 'scope' variables. (I'm not sure if this was your intent, forkit, but) a class object can live on the stack just as easily as on the heap, as long as you pass by reference. The only danger is if a called function tries to own a stack allocated object, but this is a concern for heap allocated objects too. This is why C++ has moveable types and unique_ptr.

Walter, Thanks for the insightful reply! I'm getting the sense that the decision was made in order to make the language simpler. That is, ignoring struct's, D went the Java path: You can have any color you like, as long as it's grey.

I agree that C++'s organic growth allows programmers to do things they shouldn't, and requires that they be more careful. But I would not have gone from there to Java.

I think an interesting middle-ground would be a language that had "template" types - Copyable, MoveOnly, Interface, Singleton, FactoryBuilt, etc. I've learned from all the projects that I've been on that we need all these types. We can either ask programmers to hand-craft them, or we can provide them. Note that in C++, we can get pretty close:

class Foo: Moveable<Foo> { ...

And then there's the segfault issue. I think that, if we're going to ignore a huge problem like that, there has to be very strong reasons. From this discussion, it doesn't sound like they were very strong.

Of course, it's done and there's little changing it. A seemingly harmless fix would be to not require 'new':

Foo foo; // this allocates an object
Foo foo = null; // this does not
Foo foo = function(); // this doesn't either

In fact, I suspect we could make that change today and few would notice. Nevertheless, I'm still a little shocked that this isn't existing behavior.

cheers all

Reply via email to