Cheaper to pass by reference?

F

fdm

Is it cheaper to pass an argument to a function as a reference instead of a
value?:

void updateVector(MyVectorType & vec) {
...
}


If vec contains a lot of data passing it as value:

void updateVector(MyVectorType vec) {
...
}

would create a copy of the structure in the called function so I assume it
would not be a good idea to pass it as value.
 
S

Saeed Amrollahi

Is it cheaper to pass an argument to a function as a reference instead of a
value?:

void  updateVector(MyVectorType & vec) {
   ...

}

If vec contains a lot of data passing it as value:

void  updateVector(MyVectorType vec) {
   ...

}

would create a copy of the structure in the called function so I assume it
would not be a good idea to pass it as value.

Hi

Because C/C++ are based on Copy semantic by default, reference was
added to C++ for Reference semantic.
If you want to change the passed object use reference:
void updateVector(MyVectorType & vec);
If you just want to use the passed object use const reference:
void updateVector(const MyVectorType & vec);
in both cases you gain efficiency by passing the original object
rather than copying it.

Regards,
-- Saeed Amrollahi
 
A

AnonMail2005

Is it cheaper to pass an argument to a function as a reference instead of a
value?:

void  updateVector(MyVectorType & vec) {
   ...

}

If vec contains a lot of data passing it as value:

void  updateVector(MyVectorType vec) {
   ...

}

would create a copy of the structure in the called function so I assume it
would not be a good idea to pass it as value.

The rules of thumb that I use are:
1. Pass input built in types by value.

2. Pass input classes or structs by const reference.

3. Pass outputs via a reference. But we try to return the output via
a return value if there is only a single return value and it makes
sense.

Note that in more than one instance, I've come across the complaint
that "C++ is slow" and it was due to people passing huge classes and
containers of classes by value all over the place.

HTH
 
J

Juha Nieminen

2. Pass input classes or structs by const reference.

If the class or struct only has eg. two integral member variables, it
might actually be more efficient to pass it by value rather than by
reference.
 
R

Robert Hairgrove

Juha said:
If the class or struct only has eg. two integral member variables, it
might actually be more efficient to pass it by value rather than by
reference.

Well, the OP wanted to pass a std::vector ...

Although a lot of times it doesn't make any noticeable difference in
performance, I hardly believe that there exists an object type such that
it would be MORE EFFICIENT to pass by value than by reference --
especially considering that an optimizing compiler would not even have
to reserve the memory for a pointer to the object if it is const, but
merely plug in the existing memory address in the body of the function.

Even for char type, most implementations would reserve at least enough
memory on the call stack for a pointer to the object with normal
function types (of course, things can change when using
compiler-specific optimizations and passing small literal values to a
function by register, for example...).

It is definitely a good habit to always pass things by reference (const
or non-const, depending on the semantics of the code in question) if at
all possible, IMHO. It also makes the code more self-documenting, which
is worth a lot.
 
J

James Kanze

Is it cheaper to pass an argument to a function as a reference
instead of a value?:
void updateVector(MyVectorType & vec) {
...
}
If vec contains a lot of data passing it as value:
void updateVector(MyVectorType vec) {
...
}
would create a copy of the structure in the called function so
I assume it would not be a good idea to pass it as value.

The two have completely different semantics, and the best idea
is to use the one with the appropriate semantics: pass by value
when you want to pass a value, and pass by reference when the
object has identity, and the called function must refer to the
same instance as the callee.

In most places I've worked, the guideline has been to pass class
types by const reference, instead of by value. In many ways,
this could be seen as a premature optimization, but it is so
widespread, it's probably impossible to fight against it. (Note
that you can still pass a temporary to a const reference, which
is not the case for a non-const reference.)
 
J

James Kanze

The rules of thumb that I use are:
1. Pass input built in types by value.
2. Pass input classes or structs by const reference.
3. Pass outputs via a reference. But we try to return the
output via a return value if there is only a single return
value and it makes sense.

The general rule is to only have one output value, and to return
it by value. But there are a lot of exceptions, and you
shouldn't force it. Of course, return should always be by
value, unless you're returning a reference to some existing
object outside of the function.

Note too that C++ doesn't have "out" parameters: except for
return values, all you have is "in" (by value or by const
reference) and "inout" (by non-const reference). The calling
code is always required to provide a fully constructed object.
 
J

James Kanze

Well, the OP wanted to pass a std::vector ...

Which doesn't really change the issue.
Although a lot of times it doesn't make any noticeable
difference in performance, I hardly believe that there exists
an object type such that it would be MORE EFFICIENT to pass by
value than by reference

You believe very wrong. Almost universally, it is cheaper to
pass most, if not all, of the integral types by value, and
usually, it is cheaper to pass float and double by value as
well. Depending on what the function does with the parameter,
it is often cheaper to pass small class types, like complex, by
value as well.
-- especially considering that an optimizing compiler would
not even have to reserve the memory for a pointer to the
object if it is const, but merely plug in the existing memory
address in the body of the function.

The compiler can't rewrite the function every time it is called.
If the function is inline, the choice between value and
reference is largely academic, since the compiler won't actually
pass any argument anyway. If the compiler isn't inlining the
function, then pass by reference introduces an extra
indirection, which must be weighed against the cost of copying;
for something like complex, the extra indirection can often be
more expensive than the copy.
 
B

Brian Wood

The two have completely different semantics, and the best idea
is to use the one with the appropriate semantics: pass by value
when you want to pass a value, and pass by reference when the
object has identity, and the called function must refer to the
same instance as the callee.

In most places I've worked, the guideline has been to pass class
types by const reference, instead of by value.  In many ways,
this could be seen as a premature optimization, but it is so
widespread, it's probably impossible to fight against it. >

Gosh. In a marshalling context we use pass by
reference (for classes) since we don't know if
a class/container is little or huge. I see no
value to using pass by value in such a context.


Brian Wood
http://webEbenezer.net
 
J

James Kanze

On Sep 22, 6:45 am, James Kanze <[email protected]> wrote:
Gosh. In a marshalling context we use pass by
reference (for classes) since we don't know if
a class/container is little or huge. I see no
value to using pass by value in such a context.

(I suppose you're talking about demarshalling.) How does the
user call your function if the class doesn't have a default
constructor?

It's actually a non-trivial problem, since most of the types I
want to make persistent don't support copy either. The usual
solution I've seen in such cases is to provide a constructor
which takes your demarshalling data source (istream or
whatever), and have a function which does something like:
return new ClassType( source ) ;
.. But a lot depends on what you are marshalling and why.
 
B

Brian

(I suppose you're talking about demarshalling.) How does the
user call your function if the class doesn't have a default
constructor?

If someone wants to build/receive a vector<Account>,
we require a default constructor be available. If
they want to demarshall one Account, they have to
pass an Account object to the function -- the object
in that case could have been constructed by a ctor
other than the default constructor. It seems like
I read that C++0X containers require value types
to have default constructors also.
It's actually a non-trivial problem, since most of the types I
want to make persistent don't support copy either.  The usual
solution I've seen in such cases is to provide a constructor
which takes your demarshalling data source (istream or
whatever), and have a function which does something like:
    return new ClassType( source ) ;


Currently we support both return codes and exceptions
for error handling. If we were to drop support for
return codes, I'd be more inclined to support
streaming constructors. In that case, we could use
that constructor with a vector<Account> and not
need to use a default constructor. Do you have
cases where you can't have a default constructor?

There is some tension though with the idea of
message support here. Say there are classes
A and B and a message that consists of an A
object followed by a B object. Currently I
would have a Send function like so
Send(Buffer buf, const A& abt1, const B& abt2);

and a Receive function

Receive(Buffer buf, A& abt1, B& abt2); .

The implementation of Send would send
a message id and the appropriate Receive
function would be called based on what
message id is received. It seems that
avoiding default constructors in this
case would make it more difficult to
preserve the message concept/automation;
users would have to make sure they
correctly maintained the order of the
marshalled objects themselves.


Brian Wood
http://webEbenezer.net
 
B

Brian

If someone wants to build/receive a vector<Account>,
we require a default constructor be available.  If
they want to demarshall one Account, they have to
pass an Account object to the function -- the object
in that case could have been constructed by a ctor
other than the default constructor.   It seems like
I read that C++0X containers require value types
to have default constructors also.


Currently we support both return codes and exceptions
for error handling.  If we were to drop support for
return codes, I'd be more inclined to support
streaming constructors.  In that case, we could use
that constructor with a vector<Account> and not
need to use a default constructor.  Do you have
cases where you can't have a default constructor?

There is some tension though with the idea of
message support here.  Say there are classes
A and B and a message that consists of an A
object followed by a B object.  Currently I
would have a Send function like so
Send(Buffer buf, const A& abt1, const B& abt2);

and a Receive function

Receive(Buffer buf, A& abt1, B& abt2); .

The implementation of Send would send
a message id and the appropriate Receive
function would be called based on what
message id is received.   It seems that
avoiding default constructors in this
case would make it more difficult to
preserve the message concept/automation;
users would have to make sure they
correctly maintained the order of the
marshalled objects themselves.

What I wrote above was based on a message that
I would describe with this syntax: (A, B).
One could also write (A*, B*) and the resulting
methods would be:
Send(Buffer buf, A* abt1, B* abt2); and
Receive(Buffer buf, A*& abt1, B*& abt2); .
If we added support for stream construction,
we'd use that as you indicated and the user
would be expected to take over the ownership
of the objects. I should have included
something about this in my post yesterday.


Brian Wood
http://webEbenezer.net
 

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,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top