digitalmars.D - Initialization vs Assignment
- =?UTF-8?B?Ikx1w61z?= Marques" (63/63) Nov 03 2013 Hi,
- jerro (3/8) Nov 03 2013 Actually, there is nothing wrong with calling free on a null
- =?UTF-8?B?Ikx1w61z?= Marques" (3/11) Nov 03 2013 Oops, right, not the best example. But you get the motivating
- Peter Alexander (5/5) Nov 03 2013 It's fixed in 2.064 :-)
- Kenji Hara (11/70) Nov 03 2013 a
- =?UTF-8?B?Ikx1w61z?= Marques" (5/12) Nov 03 2013 This is really weird. Not the first time that it happens to me. I
- Kozzi (19/83) Nov 03 2013 for actual version of dmd, you can use this trick :)
Hi, Most of the time my D code has been high-level, so I had never considered the following issue. Imagine you have a struct A as a member of a class/struct X (here a struct, to ensure the dtor is called): struct A { int v; this(int v) { this.v = v*2; } ~this() { writefln("~A(%d)", v); } } struct X { A a; this(int v) { a = A(v); writeln("-"); } } void main() { X x = X(42); } Output: ~A(0) - ~A(84) That is, because we don't have C++'s colon initialization syntax, we are paying the cost of initializing (and then destroying) X.a before we assign to it with "a = A(v)" in X's ctor. This seems to be the case even with disable A.this(), which here does not seem to do anything (does not prevent the default/implicit initialization of X.a, before it is assigned A(v) ). If C++ distinguishes between initialization and assignment to avoid this issue, is there a reason why D can avoid making the distinction? That is a performance issue. How about correctness? For instance: struct A { void* mem; disable this(); this(int v) { mem = malloc(v); } ~this() { free(mem); } } Now we can't have an A as a member of X? (it would free a null pointer) How have you solved these cases? Do you change it to a PIMPL? What if that's not desirable? What if you don't want to break encapsulation / cleanliness too much? Etc. Is there a good general solution for this issue?
Nov 03 2013
Now we can't have an A as a member of X? (it would free a null pointer)Actually, there is nothing wrong with calling free on a null pointer. From the C 89 standard:The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs.
Nov 03 2013
On Sunday, 3 November 2013 at 16:01:44 UTC, jerro wrote:Oops, right, not the best example. But you get the motivating idea :-)Now we can't have an A as a member of X? (it would free a null pointer)Actually, there is nothing wrong with calling free on a null pointer. From the C 89 standard:The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs.
Nov 03 2013
It's fixed in 2.064 :-) http://dpaste.dzfl.pl/c292229f Application output: - ~A(84)
Nov 03 2013
2013/11/4 <luis luismarques.eu>" puremagic.com <"\"Lu=C3=ADs".Marques">Hi, Most of the time my D code has been high-level, so I had never considered the following issue. Imagine you have a struct A as a member of a class/struct X (here a struct, to ensure the dtor is called): struct A { int v; this(int v) { this.v =3D v*2; } ~this() { writefln("~A(%d)", v); } } struct X { A a; this(int v) { a =3D A(v); writeln("-"); } } void main() { X x =3D X(42); } Output: ~A(0) - ~A(84) That is, because we don't have C++'s colon initialization syntax, we are paying the cost of initializing (and then destroying) X.a before we assig=nto it with "a =3D A(v)" in X's ctor. This seems to be the case even with disable A.this(), which here does not seem to do anything (does not prevent the default/implicit initialization of X.a, before it is assigned A(v) ). If C++ distinguishes between initialization and assignment to avoid this issue, is there a reason why D can avoid making the distinction? That is =aperformance issue. How about correctness? For instance: struct A { void* mem; disable this(); this(int v) { mem =3D malloc(v); } ~this() { free(mem); } } Now we can't have an A as a member of X? (it would free a null pointer) How have you solved these cases? Do you change it to a PIMPL? What if that's not desirable? What if you don't want to break encapsulation / cleanliness too much? Etc. Is there a good general solution for this issu=e?The issue is timely fixed in 2.064. http://d.puremagic.com/issues/show_bug.cgi?id=3D9665 https://github.com/D-Programming-Language/dlang.org/pull/404 Therefore with 2.064, the first test case will output following: - ~A(84) Kenji Hara
Nov 03 2013
On Sunday, 3 November 2013 at 16:08:26 UTC, Kenji Hara wrote:The issue is timely fixed in 2.064. http://d.puremagic.com/issues/show_bug.cgi?id=9665 https://github.com/D-Programming-Language/dlang.org/pull/404 Therefore with 2.064, the first test case will output following: - ~A(84) Kenji HaraThis is really weird. Not the first time that it happens to me. I swear that I'm not reading the pull requests and coming up with made up questions, hah :-) I guess it's a good sign of bug fixing speed!
Nov 03 2013
On Sunday, 3 November 2013 at 15:38:30 UTC, Luís Marques wrote:Hi, Most of the time my D code has been high-level, so I had never considered the following issue. Imagine you have a struct A as a member of a class/struct X (here a struct, to ensure the dtor is called): struct A { int v; this(int v) { this.v = v*2; } ~this() { writefln("~A(%d)", v); } } struct X { A a; this(int v) { a = A(v); writeln("-"); } } void main() { X x = X(42); } Output: ~A(0) - ~A(84) That is, because we don't have C++'s colon initialization syntax, we are paying the cost of initializing (and then destroying) X.a before we assign to it with "a = A(v)" in X's ctor. This seems to be the case even with disable A.this(), which here does not seem to do anything (does not prevent the default/implicit initialization of X.a, before it is assigned A(v) ). If C++ distinguishes between initialization and assignment to avoid this issue, is there a reason why D can avoid making the distinction? That is a performance issue. How about correctness? For instance: struct A { void* mem; disable this(); this(int v) { mem = malloc(v); } ~this() { free(mem); } } Now we can't have an A as a member of X? (it would free a null pointer) How have you solved these cases? Do you change it to a PIMPL? What if that's not desirable? What if you don't want to break encapsulation / cleanliness too much? Etc. Is there a good general solution for this issue?for actual version of dmd, you can use this trick :) struct A { int v; void opAssign(int v) { this.v = v; } static int opCall(int v) { return v * 2; } ~this() { writefln("~A(%d)", v); } }
Nov 03 2013