Differences between these three signatures....

X

xz

I just wanna confirm my understanding about the differences between
the signatures as follows, which are called all in the same way:

void foo(Vertex a, Vertex b, Vertex c);
void foo(Vertex & a, Vertex & b, Vertex & c);
void foo(const Vertex & a, const Vertex & b, const Vertex & c);

In the first one, the function actually works on the local copies of
a, b and c. Whatever happens inside foo does not change anything in
the outside world.

In the second one, the function operates on the original copies of a,
b and c. Whatever foo does to a, b and c inside the function
immediately applies on the a, b and c in the outside world.

In the third one, the function operates on the original copies of a, b
and c. However it cannot change anything about a, b or c.

Is that always true, no matter how the copy-constructor of Vertex is
defined?

Basically, people use the first way when they need to only locally
change something of a, b, c but do not want that change influence the
original a, b, and c in the outside world.

People use the second way when they do want the changes to a, b, and c
apply to the original a, b, and c in the outside world. In this case,
a, b, c are actually like returned result.

People use the third way when they don't need to change anything about
a, b, and c in the function, i.e. they only read a, b, and c, and
meanwhile, they want to promote the memory-efficiency.

Is that understanding correct?
 
R

rpgfan3233

I just wanna confirm my understanding about the differences between
the signatures as follows, which are called all in the same way:

void foo(Vertex a, Vertex b, Vertex c);
void foo(Vertex & a, Vertex & b, Vertex & c);
void foo(const Vertex & a, const Vertex & b, const Vertex & c);

In the first one, the function actually works on the local copies of
a, b and c. Whatever happens inside foo does not change anything in
the outside world.

In the second one, the function operates on the original copies of a,
b and c. Whatever foo does to a, b and c inside the function
immediately applies on the a, b and c in the outside world.

In the third one, the function operates on the original copies of a, b
and c. However it cannot change anything about a, b or c.

Is that always true, no matter how the copy-constructor of Vertex is
defined?

Basically, people use the first way when they need to only locally
change something of a, b, c but do not want that change influence the
original a, b, and c in the outside world.

People use the second way when they do want the changes to a, b, and c
apply to the original a, b, and c in the outside world. In this case,
a, b, c are actually like returned result.

People use the third way when they don't need to change anything about
a, b, and c in the function, i.e. they only read a, b, and c, and
meanwhile, they want to promote the memory-efficiency.

Is that understanding correct?

Yes, you are correct.
void foo(Vertex a, Vertex b, Vertex c);
Objects a, b, and c merely hold copies of the objects passed as
parameters of the function call to foo(). Objects a, b, and c are able
to be changed, and the changes WILL NOT affect the original objects.
void foo(Vertex & a, Vertex & b, Vertex & c);
Objects a, b, and c are references to the objects passed as parameters
of the function call to foo(). Objects a, b, and c are able to be
changed, and the changed WILL affect the original objects.
void foo(const Vertex & a, const Vertex & b, const Vertex & c);
Objects a, b, and c are references to the objects passed as
parameters, except that the object CANNOT be changed (reference to a
const Vertex object). This is often used when the function does not
modify the object or when the function MUST NOT change the value. A
simple pow() function can use this since pow() only returns a new
value; it doesn't modify any of its arguments.
 
N

Neelesh Bodas

I just wanna confirm my understanding about the differences between
the signatures as follows, which are called all in the same way:

void foo(Vertex a, Vertex b, Vertex c);
void foo(Vertex & a, Vertex & b, Vertex & c);
void foo(const Vertex & a, const Vertex & b, const Vertex & c);

In the first one, the function actually works on the local copies of
a, b and c. Whatever happens inside foo does not change anything in
the outside world.
Yes, provided that the copy constructor for Vertex is accessible.
In the second one, the function operates on the original copies of a,
b and c. Whatever foo does to a, b and c inside the function
immediately applies on the a, b and c in the outside world.

yes, if by "outside world" you mean the objects in the caller
function. Further, if the caller function has these objects as const /
temporaries, they cannot be used as arguments to foo - since foo takes
non-const references.
In the third one, the function operates on the original copies of a, b
and c. However it cannot change anything about a, b or c.

true.

Is that always true, no matter how the copy-constructor of Vertex is
defined?

Provided it is accessible. (2) and (3) use references, and hence donot
need a copy constructor.
Basically, people use the first way when they need to only locally
change something of a, b, c but do not want that change influence the
original a, b, and c in the outside world.

People use the second way when they do want the changes to a, b, and c
apply to the original a, b, and c in the outside world. In this case,
a, b, c are actually like returned result.

People use the third way when they don't need to change anything about
a, b, and c in the function, i.e. they only read a, b, and c, and
meanwhile, they want to promote the memory-efficiency.

Is that understanding correct?

AFAIK, yes.
 
P

Paavo Helde

I just wanna confirm my understanding about the differences between
the signatures as follows, which are called all in the same way:

void foo(Vertex a, Vertex b, Vertex c);
void foo(Vertex & a, Vertex & b, Vertex & c);
void foo(const Vertex & a, const Vertex & b, const Vertex & c);

In the first one, the function actually works on the local copies of
a, b and c. Whatever happens inside foo does not change anything in
the outside world.

Correct (unless foo accesses objects on a namespace level or causes other
side effects).
In the second one, the function operates on the original copies of a,
b and c. Whatever foo does to a, b and c inside the function
immediately applies on the a, b and c in the outside world.

In the third one, the function operates on the original copies of a, b
and c. However it cannot change anything about a, b or c.

Unless it casts away constness or modifies mutable members of a,b,c or
calls const member functions of a, b, c which do the same.
Is that always true, no matter how the copy-constructor of Vertex is
defined?

The copy-ctor is used only by the first call. It constructs a new object
physically always. However, the Vertex class author may have designed the
class as a "handle class" where the actual implementation is in a
separate object accessed via a pointer or reference. If the copy ctor of
Vertex now decides to share the same implementation, then one can easily
modify it also in the first example.
Basically, people use the first way when they need to only locally
change something of a, b, c but do not want that change influence the
original a, b, and c in the outside world.

Or if they don't want to change a, b, c, but it would be faster to copy
the objects than to access them through references. This applies if the
Vertex class is a small value class and cheap to copy.
People use the second way when they do want the changes to a, b, and c
apply to the original a, b, and c in the outside world. In this case,
a, b, c are actually like returned result.

Correct. In my code I also use such parameters for swapping out their
content to somewhere else, thus they act rather as input data generators
than output items.
People use the third way when they don't need to change anything about
a, b, and c in the function, i.e. they only read a, b, and c, and
meanwhile, they want to promote the memory-efficiency.

They could change the objects by casting away the constness, but this is
generally considered a bad thing. Also in some cases the first way cannot
be used because objects are not copyable (no public copy ctor), the third
way is then the closest approximation of by-value passing.
Is that understanding correct?

Yes, but there are more details (as always!)

hth
Paavo
 
J

James Kanze

I just wanna confirm my understanding about the differences
between the signatures as follows, which are called all in the
same way:
void foo(Vertex a, Vertex b, Vertex c);
void foo(Vertex & a, Vertex & b, Vertex & c);
void foo(const Vertex & a, const Vertex & b, const Vertex & c);
In the first one, the function actually works on the local copies of
a, b and c. Whatever happens inside foo does not change anything in
the outside world.
In the second one, the function operates on the original copies of a,
b and c. Whatever foo does to a, b and c inside the function
immediately applies on the a, b and c in the outside world.
In the third one, the function operates on the original copies of a, b
and c. However it cannot change anything about a, b or c.

Sort of. That's generally the intent, but from a language point
of view: it can modify mutable elements, it can cast away the
const (which is generally considered very bad programming
style), and it can modify the object through other expressions
which refer to it---if e.g. the function is called with a
referring to a global variable, it can always access the global
variable.
Is that always true, no matter how the copy-constructor of Vertex is
defined?

Sort of. If the copy-constructor isn't accessible, you can't
call the first at all, and you can't call the third with a
temporary (although this restriction is being dropped, I think).
Basically, people use the first way when they need to only
locally change something of a, b, c but do not want that
change influence the original a, b, and c in the outside
world.
People use the second way when they do want the changes to a,
b, and c apply to the original a, b, and c in the outside
world. In this case, a, b, c are actually like returned
result.
People use the third way when they don't need to change
anything about a, b, and c in the function, i.e. they only
read a, b, and c, and meanwhile, they want to promote the
memory-efficiency.
Is that understanding correct?

Basically. They also use one of the last two when the object
doesn't support copy, which is a fairly frequent case in many
applications.
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top