digitalmars.D - Pointers vs. References
- Michael Neumann <mneumann ntecs.de> Jun 13 2007
- Lionello Lunesu <lio lunesu.remove.com> Jun 13 2007
- Dan <murpsoft hotmail.com> Jun 13 2007
- Daniel Keep <daniel.keep.lists gmail.com> Jun 13 2007
- BCS <BCS pathlink.com> Jun 13 2007
- Michael Neumann <mneumann ntecs.de> Jun 13 2007
- Bill Baxter <dnewsgroup billbaxter.com> Jun 13 2007
- Ary Manzana <ary esperanto.org.ar> Jun 13 2007
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Jun 13 2007
- Georg Wrede <georg nospam.org> Jun 13 2007
- OF <dummy nospam.org> Jun 13 2007
- Extrawurst <spam extrawurst.org> Jun 13 2007
- Georg Wrede <georg nospam.org> Jun 13 2007
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Jun 13 2007
- Georg Wrede <georg nospam.org> Jun 13 2007
- "Kristian Kilpi" <kjkilpi gmail.com> Jun 14 2007
- Bill Baxter <dnewsgroup billbaxter.com> Jun 13 2007
- Myron Alexander <someone somewhere.com> Jun 13 2007
- Bill Baxter <dnewsgroup billbaxter.com> Jun 13 2007
- Myron Alexander <someone somewhere.com> Jun 14 2007
- Oskar Linde <oskar.lindeREM OVEgmail.com> Jun 14 2007
- Regan Heath <regan netmail.co.nz> Jun 14 2007
- "Kristian Kilpi" <kjkilpi gmail.com> Jun 14 2007
- Michael Neumann <mneumann ntecs.de> Jun 14 2007
Hi,
What I find confusing in D is the difference between references and
pointers. References server somehow the same purpose.
What are the impacts on using references instead of pointers? (e.g.
Neuron instead of Neuron*). Is there some GC magic involved for
references? I've ported a pulsed neuronal network simulator from C++ to
see how it behaves performance wise in D, but there must be really
something wrong in D (or in my implementation), as it's at least 4x
slower (and when the datasets grow, it takes infinitively long time).
And I guess I also found a bug in gdc:
Synapse x = ...;
while (x != null)
{
}
This segfaults, while:
Synapse x = ...
while (!(x is null))
{
}
does not.
Best regards,
Michael
Jun 13 2007
Michael Neumann wrote:Synapse x = ...; while (x != null) { } This segfaults, while: Synapse x = ... while (!(x is null)) { } does not.
That's not a bug. '==' and '!=' result in a call to opEquals, which is likely to segfault when one of the operands is null. You should use 'is' or in your case '!is'. while (x !is null) { } As for your question about references. A reference is basically the same as a pointer, so there should be no performance difference between the two. Without more details, it's hard to say what could be the reason behind the bad performance. L.
Jun 13 2007
Lionello Lunesu Wrote:Michael Neumann wrote:Synapse x = ...; while (x != null) { } This segfaults, while: Synapse x = ... while (!(x is null)) { } does not.
That's not a bug. '==' and '!=' result in a call to opEquals, which is likely to segfault when one of the operands is null. You should use 'is' or in your case '!is'. while (x !is null) { } As for your question about references. A reference is basically the same as a pointer, so there should be no performance difference between the two. Without more details, it's hard to say what could be the reason behind the bad performance. L.
Heh... using classes in any language will cut your performance compared to using structs. D has nice structs. References are pointers to pointers to something; not "the same". Also, using while(x !is null) after explicitly defining it is usually wrong; you usually want do { ... } while(x !is null); That's all I can gather though from your vague post.
Jun 13 2007
As for your question about references. A reference is basically the same as a pointer, so there should be no performance difference between the two. Without more details, it's hard to say what could be the reason behind the bad performance. L.
Heh... using classes in any language will cut your performance compared to using structs. D has nice structs. References are pointers to pointers to something; not "the same". Also, using while(x !is null) after explicitly defining it is usually wrong; you usually want do { ... } while(x !is null); That's all I can gather though from your vague post.
Odd; last time I looked at disassembled machine code that used references, they sure as hell looked like pointers... -- Daniel
Jun 13 2007
Daniel Keep wrote:As for your question about references. A reference is basically the same as a pointer, so there should be no performance difference between the two. Without more details, it's hard to say what could be the reason behind the bad performance. L.
Heh... using classes in any language will cut your performance compared to using structs. D has nice structs. References are pointers to pointers to something; not "the same". Also, using while(x !is null) after explicitly defining it is usually wrong; you usually want do { ... } while(x !is null); That's all I can gather though from your vague post.
Odd; last time I looked at disassembled machine code that used references, they sure as hell looked like pointers... -- Daniel
{ } Foo ref; // reference (pointer) to object Foo* ptr; // pointer to reference (pointer) to object The point that should be remembered is that objects already have reference semantics and classType* is almost never of any use.
Jun 13 2007
Dan wrote:Lionello Lunesu Wrote:Michael Neumann wrote:Synapse x = ...; while (x != null) { } This segfaults, while: Synapse x = ... while (!(x is null)) { } does not.
'==' and '!=' result in a call to opEquals, which is likely to segfault when one of the operands is null. You should use 'is' or in your case '!is'. while (x !is null) { } As for your question about references. A reference is basically the same as a pointer, so there should be no performance difference between the two. Without more details, it's hard to say what could be the reason behind the bad performance. L.
Heh... using classes in any language will cut your performance compared to using structs. D has nice structs. References are pointers to pointers to something; not "the same". Also, using while(x !is null) after explicitly defining it is usually wrong; you usually want do { ... } while(x !is null); That's all I can gather though from your vague post.
Thanks for all your answers. Well, the C++ version of course uses classes as well. It's a literal translation from C++ to D. For those interested, the source is available via my mercurial repository at: http://ntecs.de/hg-projects/inspire/ (branch "d"). hg clone static-http://ntecs.de/hg-projects/inspire/ cd inspire hg update -C d Regards, Michael
Jun 13 2007
Lionello Lunesu wrote:Michael Neumann wrote:Synapse x = ...; while (x != null) { } This segfaults, while: Synapse x = ... while (!(x is null)) { } does not.
That's not a bug. '==' and '!=' result in a call to opEquals, which is likely to segfault when one of the operands is null. You should use 'is' or in your case '!is'. while (x !is null) { } As for your question about references. A reference is basically the same as a pointer, so there should be no performance difference between the two. Without more details, it's hard to say what could be the reason behind the bad performance. L.
This issue comes up frequently enough that I'm starting to think "check against null literal" should maybe be special cased. It even bites me from time to time and I know what I'm supposed to do. --bb
Jun 13 2007
Lionello Lunesu escribió:That's not a bug. '==' and '!=' result in a call to opEquals, which is likely to segfault when one of the operands is null. You should use 'is' or in your case '!is'.
Can't writing x == null, x != null be rewritten by the compiler to x is null, x !is null ? I think the two firsts will always segfault. When would a user want to segfault her program? Or, better asked, when would a user want to do x == null? Regards, Ary
Jun 13 2007
"Ary Manzana" <ary esperanto.org.ar> wrote in message news:f4ombu$16mp$1 digitalmars.com...Can't writing x == null, x != null be rewritten by the compiler to x is null, x !is null ? I think the two firsts will always segfault. When would a user want to segfault her program? Or, better asked, when would a user want to do x == null?
I don't think the compiler should rewrite it, but I don't think it should be allowed either. Either make it a warning or an error to ==/!= to null.
Jun 13 2007
Jarrett Billingsley wrote:"Ary Manzana" <ary esperanto.org.ar> wrote in message news:f4ombu$16mp$1 digitalmars.com...Can't writing x == null, x != null be rewritten by the compiler to x is null, x !is null ? I think the two firsts will always segfault. When would a user want to segfault her program? Or, better asked, when would a user want to do x == null?
I don't think the compiler should rewrite it, but I don't think it should be allowed either. Either make it a warning or an error to ==/!= to null.
Count me in. While I'd prefer to use x == null, I can understand that it may be bad from a language design point. It would create an anomaly (because it artificially avoids calling a member function) which is misleading and requires one to remember it when reasoning about the language. So, instead, it should not be allowed. It should be an error. It is a construct the programmer didn't intend to write. :-) And which will bite him, period.
Jun 13 2007
Georg Wrede Wrote:Jarrett Billingsley wrote:"Ary Manzana" <ary esperanto.org.ar> wrote in message I don't think the compiler should rewrite it, but I don't think it should be allowed either. Either make it a warning or an error to ==/!= to null.
Count me in.
Count me in too. I've had problems with this. At least a warning would be nice.
Jun 13 2007
OF schrieb:Georg Wrede Wrote:Jarrett Billingsley wrote:"Ary Manzana" <ary esperanto.org.ar> wrote in message I don't think the compiler should rewrite it, but I don't think it should be allowed either. Either make it a warning or an error to ==/!= to null.
Count me in too. I've had problems with this. At least a warning would be nice.
definitely ! i ran into this very often and i know many D beginners who do. a warning cant hurt
Jun 13 2007
Extrawurst wrote:OF schrieb:Georg Wrede Wrote:Jarrett Billingsley wrote:"Ary Manzana" wrote
I don't think the compiler should rewrite it, but I don't think it should be allowed either. Either make it a warning or an error to ==/!= to null.
Count me in.
Count me in too. I've had problems with this. At least a warning would be nice.
definitely ! i ran into this very often and i know many D beginners who do. a warning cant hurt
Actually, why do we use the foo !is null idiom at all? (Or try to use the foo != null idiom?) The following works as expected: import std.stdio; void main() { Object o = new Object; // while(o !is null) while(o) { writefln("Yee."); o = null; } Object o2; while(!o2) { writefln("Haw."); o2 = new Object; } } The expected output being: Yee. Haw. Embarrassingly, I don't seem to remember if there was a historical reason for not (at some time?) using "while(o)". Anyhow, this would seem to be the canonical way to do it in a C family language in the first place. So maybe we should (of course first mark o==null as an error, and then) amend the documentation to suggest o itself as the Politically Correct test for nullness. Finally, the *error message* should suggest o itself for the test.
Jun 13 2007
"Georg Wrede" <georg nospam.org> wrote in message news:467045F1.6030603 nospam.org...Actually, why do we use the foo !is null idiom at all? (Or try to use the foo != null idiom?) Anyhow, this would seem to be the canonical way to do it in a C family language in the first place. So maybe we should (of course first mark o==null as an error, and then) amend the documentation to suggest o itself as the Politically Correct test for nullness.
Except there's one tiny inconsistency in the language. assert(o); This stupidly does not check that o is non-null; instead it runs the object's invariants. Which, if o really _is_ null, will cause an access violation. Whee. In this case, you have to write: assert(o !is null); Other syntaxes to run the invariant, such as "o.invariant()" or "o.assert()" have been proposed, but as usual nothing has come of it.
Jun 13 2007
Jarrett Billingsley wrote:"Georg Wrede" <georg nospam.org> wroteActually, why do we use the foo !is null idiom at all? (Or try to use the foo != null idiom?) Anyhow, this would seem to be the canonical way to do it in a C family language in the first place. So maybe we should (of course first mark o==null as an error, and then) amend the documentation to suggest o itself as the Politically Correct test for nullness.
Except there's one tiny inconsistency in the language. assert(o); This stupidly does not check that o is non-null; instead it runs the object's invariants. Which, if o really _is_ null, will cause an access violation. Whee.
Geez!!! There better be a seriously solid reason for it!In this case, you have to write: assert(o !is null); Other syntaxes to run the invariant, such as "o.invariant()" or "o.assert()" have been proposed, but as usual nothing has come of it.
An assert test is not the place to gratuituously save a few keystrokes! If anywhere, here clarity of expression and consistency are simply essential. If a programmer wants to assert there is an o, the first thing he'd do (unless too familiar with the above, er, interesting properties of D) is write assert(o); If a programmer wants to assert that the o object is happy and feels well, then we should have him write it explicitly. Dammit! assert(o.invariant()); or assert(o.assert()); or even assert(o.thisObjectIsHappy()); Making shortcuts (and saving keystrokes) _in the wrong place_ has historically led to grievances and wasted productivity few of us can fathom. Don't let this be another example. --- (Getting my adrenaline up here...) If there *ever* was a place where obscurity, short cuts, the unexpected, or inconsistency, are NOT welcome, it is debugging related code. For chrissake! And anybody who finds himself needing to write "assert(o&&o.assert());" five times a day, might consider putting this in F1 as an editor macro. --- After a cigarrette on the balcony, and proofreading, I got to the notion that the current behavior is trying to kill two flies in one stroke. assert(o) wants to give an access violation if o doesn't exist, and an assert failed if the object was unhappy. Well, I'm sorry but that's not good enough. As if what I've written above isn't enough, there's one more thing: testing whether we have an object at all, and testing whether it is happy, belong to entirely different phases of debugging. Rule #1 of debugging is, one step at a time. Still insist on testing both? Write two lines! Hey, _both_ your boss, and you yourself, should be able to understand the code (including the debugging statements) even after the Summer vacation.
Jun 13 2007
On Wed, 13 Jun 2007 23:32:10 +0300, Jarrett Billingsley <kb3ctd2 yahoo.com> wrote: <snip>assert(o); This stupidly does not check that o is non-null; instead it runs the object's invariants. Which, if o really _is_ null, will cause an access violation. Whee. In this case, you have to write: assert(o !is null); Other syntaxes to run the invariant, such as "o.invariant()" or "o.assert()" have been proposed, but as usual nothing has come of it.
I think this deserves its own thread, again. ;) So, I have created one: "Suggestion: "fix" assert(obj)"
Jun 14 2007
Ary Manzana wrote:Lionello Lunesu escribió:That's not a bug. '==' and '!=' result in a call to opEquals, which is likely to segfault when one of the operands is null. You should use 'is' or in your case '!is'.
Can't writing x == null, x != null be rewritten by the compiler to x is null, x !is null ? I think the two firsts will always segfault. When would a user want to segfault her program? Or, better asked, when would a user want to do x == null? Regards, Ary
Why not have the compiler just rewrite all equality comparisons on class objects? x == y ===> (x is y || x.opEquals(y)) I mean you might as well check first that they aren't the same object, because if they are then obviously they are equal too[1]. That would make the behavior the norm and not a special case. I don't see how doing one extra pointer comparison is going to significantly affect performance. But then I guess there's that bizzarro-business about opEquals returning an int because that's "more efficient". So I guess someone is hypersensitive about object equality operations being as fast as possible. --bb [1] Unless you're trying to implement some weirdo NaN like object which is not equal to anything, including itself.
Jun 13 2007
Bill Baxter wrote:x == y ===> (x is y || x.opEquals(y))
I prefer that the compiler does not rewrite my code. There is nothing wrong with the current syntax, it's just different from what most people here are used to. If Walter changed '==' to be a reference check, then it would mean '==' works differently for different types. That inconsistency would kick up a hurricane - precisely what happened in Java. D does get this one right but a warning would be nice. Regards, Myron.
Jun 13 2007
Myron Alexander wrote:Bill Baxter wrote:x == y ===> (x is y || x.opEquals(y))
I prefer that the compiler does not rewrite my code. There is nothing wrong with the current syntax, it's just different from what most people here are used to. If Walter changed '==' to be a reference check, then it would mean '==' works differently for different types. That inconsistency would kick up a hurricane - precisely what happened in Java. D does get this one right but a warning would be nice.
But '==' *does* work differently for different types. Already. Anyway, yeh, I'd be happy with a warning (or an error really -- unless someone can think of a case where you really _want_ to crash your program like that). --bb
Jun 13 2007
Bill Baxter wrote:But '==' *does* work differently for different types. Already.
Sorry. What I meant is that is has the same semantics. When you see ==, you can be sure that it means "check if value is the same".
Jun 14 2007
Myron Alexander skrev:Bill Baxter wrote:But '==' *does* work differently for different types. Already.
Sorry. What I meant is that is has the same semantics. When you see ==, you can be sure that it means "check if value is the same".
One could argue that = should be analogous to ==. I.e, if = assigns references, == should compare references. I am not arguing either way. :) /Oskar
Jun 14 2007
Oskar Linde Wrote:Myron Alexander skrev:Bill Baxter wrote:But '==' *does* work differently for different types. Already.
Sorry. What I meant is that is has the same semantics. When you see ==, you can be sure that it means "check if value is the same".
One could argue that = should be analogous to ==. I.e, if = assigns references, == should compare references. I am not arguing either way. :)
One could also argue that the value of a class reference is the memory address of the class to which it refers, as is the case with pointers. struct A{} A* p; A* s; if (s == p) //compares address pointer 'points' at Regan
Jun 14 2007
On Wed, 13 Jun 2007 10:09:24 +0300, Michael Neumann <mneumann ntecs.de> = = wrote: <snip>..., but there must be really something wrong in D (or in my =
implementation), as it's at least 4x slower (and when the datasets gro=
it takes infinitively long time).
Well, one thing that comes to mind is that allocating memory from the he= ap = is *slow* (in any programming language I guess). If you do that (i.e. heap allocation) inside a loop, a program will = probably get slower and slower, nonlinearly, when the loop count increas= es = (I recently noticed that in a (C++) project of mine). For example, if yo= u = have something like this in C++: void foo() { MyClass myclass; ... } void bar() { int i; for(i =3D 0; i < 1000000; i++) foo(); } , then you should use the 'scope' keyword in 'foo()' when programmin in = D: void foo() { scope MyClass myclass =3D new MyClass; //(or just plain "scope myc= lass = =3D new MyClass;") } This way 'myclass' is allocated from the stack instead of the heap. I hope this will help (that is, if you hadn't used 'scope' (in similar = cases), of course).
Jun 14 2007
Kristian Kilpi wrote:On Wed, 13 Jun 2007 10:09:24 +0300, Michael Neumann <mneumann ntecs.de> wrote: <snip>..., but there must be really something wrong in D (or in my implementation), as it's at least 4x slower (and when the datasets grow, it takes infinitively long time).
Well, one thing that comes to mind is that allocating memory from the heap is *slow* (in any programming language I guess).
Thanks. Yeah, I know! That's why I'm using a free-list in my program and recycle old objects. Regards, Michael
Jun 14 2007









BCS <BCS pathlink.com> 