use of pointers

J

Jorgen Grahn

Sounds like old-style C programmer: "I believe it is too expensive".

Of course. What I wrote was meant as an example of how C programmers
tend to think, not as a recommendation.

/Jorgen
 
B

BGB

User-defined data types improve code readability. Under some circumstances,
it also help reduce the propensity to inadvertently add bugs to the code.

yep, and in many cases where points/vectors are in use, they are a
fairly fundamental building-block type, rather than an "afterthought"
(or "misc") type, making them more suited to having their own dedicated
type-names and their own dedicated logic.


granted, a lot depends on the particular domain as well.
for example, I am prone to think of a "money" or "date" types as fairly
misc, since I don't use them much for what I do, but there are people
who write types of software where such things make a good deal more
sense (and languages like SQL treat both as fundamental types).

nevermind other strangeness (observed in accounting contexts): thinking
as dates strictly in terms of days, or even ignoring the existence of
things like leap years and similar in calculations (vs the more "sane"
option of, say, thinking as time more strictly in terms of an absolute
number of seconds, as a real value, between events).

but, it could be argued that maybe for the accountant, there is little
reason for the accountant to care if "this time next year" may easily
differ by hours or maybe days from "this time next year" as far as a
scientist or engineer would be concerned (in terms of the number of
seconds between "now" and "this date and time exactly one year from
now"...).

or, for that matter, mentioning doing something "tomorrow" when it is
after midnight, and said "tomorrow" is maybe only 10 or 14 hours away
and technically the same day (as far as the calender is concerned...).



and, say, if one writes a 3D engine, they will be seeing points,
vectors, matrices, ... quite a fair amount.

so, yeah, sometimes it makes a lot of sense to make dedicated types for
these sorts of things.
 
N

none

Knuth's quote tends to be abused a bit. Some individuals employ it to,
under Knuth's authority, imply that any attention to efficiency, however
remote it might be, is also evil, and therefore no attention whatsoever
should be ever paid to it. This may pose a serious problem in applications
which do need to run efficiently, as it isn't possible to fix performance
problems caused by fundamental design decisions by postponing any attention
to the application's efficiency to a testing stage.

The key is the difference between premature optimization and premature
pessimization. Sutter/Alexandrescu did follow their "Don't optimize
prematurely" with a "Don't pessimize prematurely". They were also
careful to define premature optimization as making code more complex
and less readable when it is not justified by a *proven* performance
need (my emphasis).

however, all other things being equal, you should know more efficient
patterns and use them naturally if there are no negative cost to using
them. This may be as simple as passing read-only parameters as const
reference rather than by value and forcing a copy. OTOH, manually
implementing a ring buffer and maniplulating internal data with
pointer arithmetic because one believe that std::vector might not be
as fast is not justfiable without measurements.

Yannick
 
M

Maarten

Knuth's quote tends to be abused a bit.

Which is why I looked it up, and used a slightly longer quotation. The
rest of the article is rather interesting.
Some individuals employ it to,
under Knuth's authority, imply that any attention to efficiency, however
remote it might be, is also evil, and therefore no attention whatsoever
should be ever paid to it. This may pose a serious problem in applications
which do need to run efficiently, as it isn't possible to fix performance
problems caused by fundamental design decisions by postponing any attention
to the application's efficiency to a testing stage.

Do things in the right order:

* Use an appropriate algorithm. This is where the greatest improvements
can be made. This is at the design-stage, not at the programming stage.
No optimization can dig you out of the hole created by picking the wrong
algorithm.

But on the other hand, spend your time wisely. Initialization is run only
once, a loop multiple times. While you may be able to make initialization
faster by 90%, on the overall run time the effect may be negligible.
Improve the code within a loop by 10%, and you might gain a lot.

* Get something that is producing the correct results. Make sure the code
is readable at this stage. Low-hanging fruit can be harvested, say by
removing calculations from a loop that produce constant results.
Do not worry about the relative efficiency of 'a != 0' vs 'a > 0'.

* Run the code, and see if performance is an issue. If not: you're done,
and you have readable code. If more performance is needed, start your profiler
and start optimizing from there.

I believe that Knuth was talking about discussion as to whether 'a != 0'
or 'a > 0' is faster. On that I agree with him. Somehow I think he would
agree with me on picking the right algorithm, and spending your time there.

Maarten
 
R

Rui Maciel

none said:
The key is the difference between premature optimization and premature
pessimization. Sutter/Alexandrescu did follow their "Don't optimize
prematurely" with a "Don't pessimize prematurely". They were also
careful to define premature optimization as making code more complex
and less readable when it is not justified by a proven performance
need (my emphasis).

Indeed, and surely the reason behind this need to clarify what Knuth said is
due to the level of abuse that Knuth's quote has been subjected since it
first appeared. After all, is it really reasonable to quote Knuth when
discussing stuff such as passing objects by value/reference?


Rui Maciel
 
N

Nobody

And I am not so sure one couldn't just return std::pair<float,float>
since it essentially does the same thing, except that its members are
not called 'x' and 'y'... Why invent another type when a standard one
exists?

1. Clarity. A specific type provides clues as to the meaning of the data.

2. Safety. If you have separate Position and Velocity types, you'll get a
type error if you try to use one where the other is required.
 
N

Nobody

Only start optimizing once you have tested your code, and are
satisfied that it is correct. And only start to optimize when
you have seen that there is a performance issue, and have
pinpointed the issue with a profiler.

The main problem there is that changing interfaces at a late stage can
require rewriting a substantial amount of code.

An important part of the programmer's art is knowing which bridges you'll
have to cross before you get to them, avoiding the need to dig yourself
out of holes by not climbing into them in the first place.
 
N

Nobody

Probably not the /only/ way though -- returning structs has been
possible in C for ~25 years now. I always believed it was expensive,
but I suspect that at some point it became cheaper with popular
compilers.

For functions with external linkage, the compiler doesn't have much
choice, as the platform's ABI will normally dictate how structures are
returned.
 
J

Jorgen Grahn

For functions with external linkage, the compiler doesn't have much
choice, as the platform's ABI will normally dictate how structures are
returned.

Yeah, but is that inefficient for any decent platforms? I don't see
why it would have to be. One which seems reasonable is:

- Less than 32 bits? Dump it in register FOO.
- More? Room has been made available on the stack <here>.

I don't see how this would make returning structs expensive, if that's
what you're trying to convey.

/Jorgen
 
P

Pavel

BGB said:
yep, and in many cases where points/vectors are in use, they are a fairly
fundamental building-block type, rather than an "afterthought" (or "misc") type,
making them more suited to having their own dedicated type-names and their own
dedicated logic.


granted, a lot depends on the particular domain as well.
for example, I am prone to think of a "money" or "date" types as fairly misc,
since I don't use them much for what I do, but there are people who write types
of software where such things make a good deal more sense (and languages like
SQL treat both as fundamental types).

nevermind other strangeness (observed in accounting contexts): thinking as dates
strictly in terms of days, or even ignoring the existence of things like leap
years and similar in calculations (vs the more "sane" option of, say, thinking
as time more strictly in terms of an absolute number of seconds, as a real
value, between events).

but, it could be argued that maybe for the accountant, there is little reason
for the accountant to care if "this time next year" may easily differ by hours
or maybe days from "this time next year" as far as a scientist or engineer would
be concerned (in terms of the number of seconds between "now" and "this date and
time exactly one year from now"...).

or, for that matter, mentioning doing something "tomorrow" when it is after
midnight, and said "tomorrow" is maybe only 10 or 14 hours away and technically
the same day (as far as the calender is concerned...).



and, say, if one writes a 3D engine, they will be seeing points, vectors,
matrices, ... quite a fair amount.

so, yeah, sometimes it makes a lot of sense to make dedicated types for these
sorts of things.
I think those suggesting change in the interface other than replacing pointers
with references spoke without trying to understand how the function is used.

For example, if the call site converts separate arrays of the two velocity
components, changing from output parameters to return type would do more harm
than good.

On a side note, even though I am not crazy about using pointers that shall not
be NULLs, I tend to think twice before changing existing APIs from pointers to
references: if significant amount of client code is "C-style" or just follows
the convention of always using pointers for output parameters, its maintainers
may assume that the arguments passed for x and y are values and misread the
code's intention.

I am seriously thinking of wrapping my passed-by-referenced parameters in "Ref"
objects with explicit constructors -- with the only goal to better document call
sites (e.g. NewPos(angle, speed, FloatRef(x), FloatRef(y));). Does anybody know
anything existing of the kind?

As for the OP's question, I would seriously think of leaving the interface as it
is -- at least until there is a domain-area-originated reason for changing it.

-Pavel
 
J

Jeff Flinn

Pavel said:
I think those suggesting change in the interface other than replacing
pointers with references spoke without trying to understand how the
function is used.

For example, if the call site converts separate arrays of the two
velocity components, changing from output parameters to return type
would do more harm than good.

std::tuple<float, float>
NewPos(float angle, float speed, float *x, float *y)
{

angle = (angle-90.0)*0.0174532925199433;

return std::make_tuple( cos(angle) * speed
, sin(angle) * speed);
}

int main()
{
...

std::tie(x, y) = NewPos(angle, speed);
}

I see no harm here, in fact the intent is more explicit.

Jeff
 
J

Jeff Flinn

Jeff said:
std::tuple<float, float>
NewPos(float angle, float speed, float *x, float *y)

Oops that should be:
std::tuple said:
{

angle = (angle-90.0)*0.0174532925199433;

return std::make_tuple( cos(angle) * speed
, sin(angle) * speed);
}

int main()
{
...

std::tie(x, y) = NewPos(angle, speed);
}

I see no harm here, in fact the intent is more explicit.

Jeff
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top