Is This rule of deciding the best method of parameter passing totallyright ?

G

Good Guy

When it's the matter of deciding the best method of parameter passing
a series of complexities would be brought up to make the decision
about whether it is efficient for the argument to be passed by address
or value in machine code level and of course there might be several
dimensions of efficiency to be considered, so it would make sense for
this matter to be left up to compiler to decide about; with that said
I've come across a tip that is claimed to be a strict rule and if a
programmer follows the guideline of this tip the compiler can do its
job then to determine the best method for parameter passing, the tip
is always write function parameters associated with primitive types
(int, long, char, double, etc...), iterators and function objects
types (don't know if I missed anything more here), in the form of pass
by value and always write function parameters associated with any user-
defined type in the form of pass by reference to constant; now I'd
like to know if this rule is totally right and then if it is an
explanation of its philosophy is appreciated, but if there's anything
wrong with this rule what that is and why.
 
V

Victor Bazarov

When it's the matter of deciding the best method of parameter passing
a series of complexities would be brought up to make the decision
about whether it is efficient for the argument to be passed by address
or value in machine code level and of course there might be several
dimensions of efficiency to be considered, so it would make sense for
this matter to be left up to compiler to decide about; with that said
I've come across a tip that is claimed to be a strict rule and if a
programmer follows the guideline of this tip the compiler can do its
job then to determine the best method for parameter passing, the tip
is always write function parameters associated with primitive types
(int, long, char, double, etc...), iterators and function objects
types (don't know if I missed anything more here), in the form of pass
by value and always write function parameters associated with any user-
defined type in the form of pass by reference to constant; now I'd
like to know if this rule is totally right and then if it is an
explanation of its philosophy is appreciated, but if there's anything
wrong with this rule what that is and why.

There is no *rule* in the world that is "totally right" in _all
circumstances_. Is that good enough an answer? I strongly recommend
you to learn to avoid absolutes in your professional activities, whether
they are coming from a book, a web site, or your manager. Avoiding
something is a tricky sport, though. You can often find another book or
another web site that says something less absolute to "prove" the other
one "wrong", but it's often difficult to find another manager for
yourself, so be prepared.

V
 
Ö

Öö Tiib

When it's the matter of deciding the best method of parameter passing
a series of complexities would be brought up to make the decision
about whether it is efficient for the argument to be passed by address
or value in machine code level and of course there might be several
dimensions of efficiency to be considered, so it would make sense for
this matter to be left up to compiler to decide about; with that said
I've come across a tip that is claimed to be a strict rule and if a
programmer follows the guideline of this tip the compiler can do its
job then to determine the best method for parameter passing, the tip
is always write function parameters associated with primitive types
(int, long, char, double, etc...), iterators and function objects
types (don't know if I missed anything more here), in the form of pass
by value and always write function parameters associated with any user-
defined type in the form of pass by reference to constant; now I'd
like to know if this rule is totally right and then if it is an
explanation of its philosophy is appreciated, but if there's anything
wrong with this rule what that is and why.

Your rule is too absolute, like Victor said else-thread.

For idealist taste C++ has way too many flavors of parameter passing.
Ideally necessary and sufficient are two flavors: A) input-only
parameter and B) input-output parameter. Rest of the details could be
up to compiler to optimize. Possibly it will be like that one day.
Until then ... just profile your product and rearrange the things on
need.

My preferences:
1) The input-output parameters I always take by reference.
2) The input-only parameter that feels cheap to copy or what I would
otherwise copy anyway inside of the function I take by value.
3) Rest of the input-only I accept as const reference.
4) On case when parameter can be optionally missing I prefer to have
overload in interface that lacks that parameter.
5) On case when parameter is representing an array I accept them as
vectors or pairs of iterators.

That is not some sort of deep or strong or full rule set ... just mine
preferences for most common cases.
 
A

AnonMail2005

When it's the matter of deciding the best method of parameter passing
a series of complexities would be brought up to make the decision
about whether it is efficient for the argument to be passed by address
or value in machine code level and of course there might be several
dimensions of efficiency to be considered, so it would make sense for
this matter to be left up to compiler to decide about; with that said
I've come across a tip that is claimed to be a strict rule and if a
programmer follows the guideline of this tip the compiler can do its
job then to determine the best method for parameter passing, the tip
is always write function parameters associated with primitive types
(int, long, char, double, etc...), iterators and function objects
types (don't know if I missed anything more here), in the form of pass
by value and always write function parameters associated with any user-
defined type in the form of pass by reference to constant; now I'd
like to know if this rule is totally right and then if it is an
explanation of its philosophy is appreciated, but if there's anything
wrong with this rule what that is and why.

As a general rule that's pretty much correct. But the rule to pass
objects by const reference needs the caveat "unless you can't".
Meaning that sometimes you will have to pass it by non-const reference
due to what the function does (e.g. modify the object).

HTH
 
G

Good Guy

When it's the matter of deciding the best method of parameter passing
a series of complexities would be brought up to make the decision
about whether it is efficient for the argument to be passed by address
or value in machine code level and of course there might be several
dimensions of efficiency to be considered, so it would make sense for
this matter to be left up to compiler to decide about; with that said
I've come across a tip that is claimed to be a strict rule and if a
programmer follows the guideline of this tip the compiler can do its
job then to determine the best method for parameter passing, the tip
is always write function parameters associated with primitive types
(int, long, char, double, etc...), iterators and function objects
types (don't know if I missed anything more here), in the form of pass
by value and always write function parameters associated with any user-
defined type in the form of pass by reference to constant; now I'd
like to know if this rule is totally right and then if it is an
explanation of its philosophy is appreciated, but if there's anything
wrong with this rule what that is and why.

After reading the source code(http://www.boost.org/doc/libs/1_45_0/
boost/detail/call_traits.hpp) found out that, Not talking about arrays
or references as arguments themselves
"boost::call_traits<T>::param_type" that claims to define the best
passing method is equivalent to "const T &" when T has a size bigger
than the size of pointer even when T is a primitive like long integer
on a platform like mine that is 4-bytes bigger in size than pointer
and "boost::call_traits<T>::param_type" is equivalent to "const T"
when T is a class/struct or primitive type with a size less than or
equal to size of the pointer, I extremely suggest anyone to go and
read the source code.
 
R

Rick Wheeler

After reading the source code(http://www.boost.org/doc/libs/1_45_0/
boost/detail/call_traits.hpp) found out that, Not talking about arrays
or references as arguments themselves
"boost::call_traits<T>::param_type" that claims to define the best
passing method is equivalent to "const T &" when T has a size bigger
than the size of pointer even when T is a primitive like long integer
on a platform like mine that is 4-bytes bigger in size than pointer
and "boost::call_traits<T>::param_type" is equivalent to "const T"
when T is a class/struct or primitive type with a size less than or
equal to size of the pointer, I extremely suggest anyone to go and
read the source code.- Hide quoted text -

- Show quoted text -

And as a general recommendation, that continues to make sense. Of
course, the "const T&" will manifest as a pointer in the final code
generation, and perhaps that's your concern. In some circumstances for
long long integers, on 32 bit machines, it might turn out to be better
to pass by value, given registering possibilities in lieu of stack
placement, but for generic programming, it may be a small consequence.

For semantic clarity and optimal information at the call site, I would
amend the recommendations stated here to:
1) Pass input only primitives by value.
2) Pass input only user types by reference to const.
3) Pass input/output primitives and user types by non-const pointer.
The latter preference is important to differentiate the otherwise
indistinguishable call by value semantics of both reference to const
and reference to non-const. Those who read your code will appreciate
it (including yourself).

Rick
 
R

Rick Wheeler

Whilst call site documentation is useful I disagree with the use of
pointers for out parameters.  One should prefer references over pointers
(this is also a preference but a widely adopted one including by the
standard library, e.g. std::list::splice).

/Leigh- Hide quoted text -

- Show quoted text -

(The following reply was sent to Leigh directly, but intended to be
here -- Thanks Leigh!)

As experience in logical systems and behaviors deepens, one eventually
learns the true insidious nature of ambiguity. It is a nemesis to
information exchange that is unrivaled in the formulation and analyses
of such things. Yet it finds safe haven unwittingly and too often.
With this understanding comes a championing of its annihilation that
cannot be overstated. Despite usage of non-const reference for outputs
in the standard library, there is no objective technical reason to
prefer it over pointer (none that I know of). And in fact, given that
it directly injects undeniable ambiguity to traditional value
semantics, it would be hard to fabricate reasoning to outweigh this.
Even though the standard library is a tremendous work, it has no
stature on this matter. While not everyone will agree, those that
might see this point of view will opt for the better way.

Rick
 
E

Ebenezer

(The following reply was sent to Leigh directly, but intended to be
here -- Thanks Leigh!)

As experience in logical systems and behaviors deepens, one eventually
learns the true insidious nature of ambiguity. It is a nemesis to
information exchange that is unrivaled in the formulation and analyses
of such things. Yet it finds safe haven unwittingly and too often.
With this understanding comes a championing of its annihilation that
cannot be overstated. Despite usage of non-const reference for outputs
in the standard library, there is no objective technical reason to
prefer it over pointer (none that I know of). And in fact, given that
it directly injects undeniable ambiguity to traditional value
semantics, it would be hard to fabricate reasoning to outweigh this.
Even though the standard library is a tremendous work, it has no
stature on this matter. While not everyone will agree, those that
might see this point of view will opt for the better way.

I not sure whether I agree with you on this. My work involves
creating marshalling code with Send and Receive functions. The
Send functions take arguments either by value or by reference to
const and the Receive functions take reference to non-const
arguments.
This simple rule is followed by the library and so ambiguity is
dispelled. In some cases considering the broader context may be
enough to support the use of reference to non-const in function
signatures.


Brian Wood
Ebenezer Enterprises
http://webEbenezer.net
http://wnd.com
 
I

Ian Collins

And as a general recommendation, that continues to make sense. Of
course, the "const T&" will manifest as a pointer in the final code
generation, and perhaps that's your concern. In some circumstances for
long long integers, on 32 bit machines, it might turn out to be better
to pass by value, given registering possibilities in lieu of stack
placement, but for generic programming, it may be a small consequence.

For semantic clarity and optimal information at the call site, I would
amend the recommendations stated here to:
1) Pass input only primitives by value.
2) Pass input only user types by reference to const.
3) Pass input/output primitives and user types by non-const pointer.
The latter preference is important to differentiate the otherwise
indistinguishable call by value semantics of both reference to const
and reference to non-const. Those who read your code will appreciate
it (including yourself).

But if you apply this rule streaming operators or marshalling code, you
end up with ugly and counter-intuitive code. For many common uses of
reference output parameters, clarity is provided by context.
 
M

Miles Bader

Ian Collins said:
But if you apply this rule streaming operators or marshalling code,
you end up with ugly and counter-intuitive code. For many common uses
of reference output parameters, clarity is provided by context.

And of course one can always simply use comments (heavens!)...

some_func (in1, in2, /*out:*/ result1, /*out:*/ result2);

tho indeed it's often obvious enough from the context...

[Still I think it would be cool to have a compiler-enforced call-site
syntax for this...]

-Miles
 
R

Rick Wheeler

I not sure whether I agree with you on this.  My work involves
creating marshalling code with Send and Receive functions.  The
Send functions take arguments either by value or by reference to
const and the Receive functions take reference to non-const
arguments.
This simple rule is followed by the library and so ambiguity is
dispelled.  In some cases considering the broader context may be
enough to support the use of reference to non-const in function
signatures.

Brian Wood
Ebenezer Enterpriseshttp://webEbenezer.nethttp://wnd.com- Hide quoted text -

- Show quoted text -

Yes, a simple case like this does allow the ambiguity to be much more
palatable, but nonetheless does not avert it. And every propagation of
the ref to non-const idiom into overall generalized practice becomes
one battle lost in the alleviation of equivocal expression. What if
you had decided to use pointers in the Receive? Interestingly, there
would have been no ambiguity to dispel. It would be an equally simple
convention, and would carry more information in all contexts. Some do
not care about such things, but for those that do, the solution is
embarassingly trivial -- pass by address, not reference for non-const.

Rick
 
Ö

Öö Tiib

Yes, a simple case like this does allow the ambiguity to be much more
palatable, but nonetheless does not avert it. And every propagation of
the ref to non-const idiom into overall generalized practice becomes
one battle lost in the alleviation of equivocal expression. What if
you had decided to use pointers in the Receive? Interestingly, there
would have been no ambiguity to dispel. It would be an equally simple
convention, and would carry more information in all contexts. Some do
not care about such things, but for those that do, the solution is
embarassingly trivial -- pass by address, not reference for non-const.

That is an attempt to give yet another meaning to a raw pointer. Raw
pointer is simply too loose thing to call a language that uses it in
masses "type safe". It can not pull the weight of signaling mutability
to reader anyway. Since operator.() can not be overloaded one has to
use pointer semantics for reference classes (like smart pointers and
iterators). Better avoid raw pointers whatsoever and leave pointer
semantics for these types only.
 
R

Rick Wheeler

But if you apply this rule streaming operators or marshalling code, you
end up with ugly and counter-intuitive code.  For many common uses of
reference output parameters, clarity is provided by context.

The streams are an excellent case to raise! But to be clear, streaming
operators do not enlist pass by value call semantics in their usage
(other than their local definition of course). And as such, you'll
find no opportunity for misinterpretation any place they appear.
That's actually important. However, generaly speaking imperative
clarity can never be provided in any local context surrounding output
reference parameters. Instead any garnered clarity comes from
elsewhere, e.g. header files, documentation, or (much worse) some kind
of assumption (say from a name like Receive).

Rick
 
E

Ebenezer

Yes, a simple case like this does allow the ambiguity to be much more
palatable, but nonetheless does not avert it. And every propagation of
the ref to non-const idiom into overall generalized practice becomes
one battle lost in the alleviation of equivocal expression. What if
you had decided to use pointers in the Receive?

It opens the function up to null pointers being supplied. I'm not
sure of my view on the overall question here and will wait to read
what others have to say.


Brian Wood
 
E

Ebenezer

The streams are an excellent case to raise! But to be clear, streaming
operators do not enlist pass by value call semantics in their usage
(other than their local definition of course). And as such, you'll
find no opportunity for misinterpretation any place they appear.
That's actually important. However, generaly speaking imperative
clarity can never be provided in any local context surrounding output
reference parameters. Instead any garnered clarity comes from
elsewhere, e.g. header files, documentation, or (much worse) some kind
of assumption (say from a name like Receive).

I use the word convention rather than assumption. And it is a
documented convention.
 
E

Ebenezer

The streams are an excellent case to raise! But to be clear, streaming
operators do not enlist pass by value call semantics in their usage
(other than their local definition of course). And as such, you'll
find no opportunity for misinterpretation any place they appear.
That's actually important. However, generaly speaking imperative
clarity can never be provided in any local context surrounding output
reference parameters. Instead any garnered clarity comes from
elsewhere, e.g. header files, documentation, or (much worse) some kind
of assumption (say from a name like Receive).

I use the word convention rather than assumption here and it
is a documented convention in my case.

Brian Wood
 
B

Bart van Ingen Schenau

[snip] Despite usage of non-const reference for outputs
in the standard library, there is no objective technical reason to
prefer it over pointer (none that I know of). And in fact, given that
it directly injects undeniable ambiguity to traditional value
semantics, it would be hard to fabricate reasoning to outweigh this.
Even though the standard library is a tremendous work, it has no
stature on this matter. While not everyone will agree, those that
might see this point of view will opt for the better way.

Unfortunately, using pointers both for mandatory and optional out-
parameters produces a new ambiguity: You can't readily know if the
contract of the function allows you to pass a null-pointer or not.

For both ambiguities you need to consult information outside the call-
site to resolve it (for the non-const reference case, the function
prototype, for the optional/mandatory case, the documentation of the
function).
As the function documentation is more likely to be unavailable or out-
of-date, I know which ambiguity is more important to eradicate.

Bart v Ingen Schenau
 
R

Rick Wheeler

[snip] Despite usage of non-const reference for outputs
in the standard library, there is no objective technical reason to
prefer it over pointer (none that I know of). And in fact, given that
it directly injects undeniable ambiguity to traditional value
semantics, it would be hard to fabricate reasoning to outweigh this.
Even though the standard library is a tremendous work, it has no
stature on this matter. While not everyone will agree, those that
might see this point of view will opt for the better way.

Unfortunately, using pointers both for mandatory and optional out-
parameters produces a new ambiguity: You can't readily know if the
contract of the function allows you to pass a null-pointer or not.

For both ambiguities you need to consult information outside the call-
site to resolve it (for the non-const reference case, the function
prototype, for the optional/mandatory case, the documentation of the
function).
As the function documentation is more likely to be unavailable or out-
of-date, I know which ambiguity is more important to eradicate.



Bart v Ingen Schenau

That's not ambiguity in the traditional sense of foisted
misinterpretation, so the similarity is vague at best. However, it is
a behavioral aspect of the "address of" mannerism that's very much
worth discussing. As a generalization, the practice should be: don't
anticipate null pointers. In fact, assert they are not null in
function implementations if you like (for commendable documentary),
although it's operationally unnecessary. Passing by non-const
reference side steps the issue by throwing responsibility of valid
objects on the caller side. That doesn't change when passing by
address. The likewise similar aspect is you wouldn't call the function
if you didn't have an object. And in both cases if you did, the effect
would be the same.

Null pointer contracts are no longer much consideration at low levels
of abstraction these days, given the move to exceptions for bad
allocations, etc. (discounting occasional legacies). However, such
contracts do regularly appear at higher design levels, fulfilling
various logical purposes. Moreover, such designs usually use pointers
for the relevant objects everywhere, for input or output, and
certainly require an understanding of the framework they impose. When
interfacing with these sorts of components, ones preferences are
perhaps a moot point.

Rick
 
E

Ebenezer

That's not ambiguity in the traditional sense of foisted
misinterpretation, so the similarity is vague at best. However, it is
a behavioral aspect of the "address of" mannerism that's very much
worth discussing. As a generalization, the practice should be: don't
anticipate null pointers. In fact, assert they are not null in
function implementations if you like (for commendable documentary),
although it's operationally unnecessary. Passing by non-const
reference side steps the issue by throwing responsibility of valid
objects on the caller side. That doesn't change when passing by
address. The likewise similar aspect is you wouldn't call the function
if you didn't have an object. And in both cases if you did, the effect
would be the same.

Null pointer contracts are no longer much consideration at low levels
of abstraction these days, given the move to exceptions for bad
allocations, etc. (discounting occasional legacies). However, such
contracts do regularly appear at higher design levels, fulfilling
various logical purposes. Moreover, such designs usually use pointers
for the relevant objects everywhere, for input or output, and
certainly require an understanding of the framework they impose. When
interfacing with these sorts of components, ones preferences are
perhaps a moot point.

I would like an example of a contract that is using pointers for
the relevant objects everywhere. My observation of using references
rather than pointers in generated middleware is the reference syntax
reduces the amount of output that has to be produced and sent to the
user. Technically you may have a strong argument, but practically
it has a drawback.

Brian Wood
 

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

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top