On Tue, Feb 24, 2015 at 06:22:05PM +0000, ketmar via Digitalmars-d-learn wrote: > On Tue, 24 Feb 2015 12:05:50 +0000, amber wrote: > > > Hi, > > > > Is it possible in D to have inheritance using value types, i.e. > > structs? > > > > Also I don't quite understand how copy ctors work in D. Do I need to > > implement opAssign(S other) {}, or this(this) {} and what's the > > difference between these two? > > > > Thanks, > > Amber > > p.s. sometimes compiler can use "move" instead of "copy" for > structures. in this case it will not call postblit. so if you have > some fields in your struct that depends of the structure address... > you're in trouble.
Yes, basically, D structs are value types, and quite unlike C++ structs. It's a trap to assume C++-like semantics for D structs, because they are actually very different beasts. D structs should not rely on their own address remaining static, because move semantics will cause problems, for example: struct S { int x; int* p; this(int _x) { x = _x; p = &x; // uh-oh } void method() { *p++; // by the time this runs, the struct may // have moved } } S makeStruct() { return S(1); } void main() { auto s = makeStruct(); s.method(); assert(s.x == 2); // KABOOM } The problem is that returning S from makeStruct() makes a bitwise copy of the struct into main's local variable s, which has a different address than the one created in makeStruct(). But s.p still points to the old address of s.x, which is now pointing to invalid memory. For even more fun, do this: void checkItOut(int x, S* s) { assert(x == 10); s.method(); assert(x == 10); // KABOOM } void main() { auto s = makeStruct(); s.method(); checkItOut(10, &s); } Depending on the specifics of your platform, the second assert in checkItOut() may fail, because s.method(), via the stale pointer s.p, will overwrite the stack location where the original s.x was (but which has gone out of scope and is now invalid), and that old location is now being used for one of the parameters of checkItOut(). So calling s.method() will silently corrupt the stack where the parameter is passed. tl;dr, the moral of the story is, don't rely on the address of structs in D staying the same, unless you REALLY know what you're doing. And even then, you're just 1/8 of an inch away from shooting yourself in the foot. T -- All problems are easy in retrospect.