why should one use "&" in "const char*const& szString"

A

alariq

Can some one explain me why should one use this construction. Is there
any need for "&" ?
Is there any difference between those 2 options: (excluding that in
first case *szString is passed by value and in second - by reference):
1) const char*const& szString
2) const char*const szString


Thanks is andvance
 
I

itaj sherman

Can some one explain me why should one use this construction. Is there
any need for "&"  ?
Is there any difference between those 2 options: (excluding that in
first case *szString is passed by value and in second - by reference):
1) const char*const& szString
2) const char*const szString

Thanks is andvance

if you're talking about a parameter to a function as in:

void func1( char const* const& r );
void func2( char const* const r );

or in general for any copyable type T:

void func1( T const& r );
void func2( T const r );

In you're case T = char const*

The difference is that in func1, the referenced T object is const to
the code in func1, but may be non-const to someone else, who can
change it. On the other hand in func2, once the funtion has been
called, it has its own object that no one else can change.
When calling func1 someone else, may change the state of the T object
and the change will be reflected on the object used by func1 (because
it is the same object). This someone else can be code in a different
thread executing at the same time as func1, or else if func1 keeps
that reference in some data structure, then even after func1 returns,
the caller of func1 can change the state of the object referred to by
that data structure.
 
I

itaj sherman

if you're talking about a parameter to a function as in:

void func1( char const* const& r );
void func2( char const* const r );

or in general for any copyable type T:

I mean, to be able to declare func2, type T needs a public copy
constructor, assignment isn't necessary.
void func1( T const& r );
void func2( T const r );

In you're case T = char const*

The difference is that in func1, the referenced T object is const to
the code in func1, but may be non-const to someone else, who can
change it. On the other hand in func2, once the funtion has been
called, it has its own object that no one else can change.
When calling func1 someone else, may change the state of the T object
and the change will be reflected on the object used by func1 (because
it is the same object). This someone else can be code in a different
thread executing at the same time as func1, or else if func1 keeps
that reference in some data structure, then even after func1 returns,
the caller of func1 can change the state of the object referred to by
that data structure.

And I don't know if compiler optimizations could change anything about
what I said.
 
P

Peter Remmers

itaj said:
> In you're case T = char const*

I find it amazing that even programmers who know the difference
between e.g. "foo->bar" and "foo.bar" sometimes don't seem to
differentiate between "you're" and "your".

Peter
 
I

itaj sherman

itaj sherman schrieb:

 > In you're case T = char const*

I find it amazing that even programmers who know the difference
between e.g. "foo->bar" and "foo.bar" sometimes don't seem to
differentiate between "you're" and "your".

Peter

I know the difference just as well as I know the difference between
foo.bar and boo->bar. It's not the same as differentiating. Sometimes
I don't seem to differentiate between foo.bar and foo->bar too, and
it's only at compile time that I find out about it.
 
J

James Kanze

In addition to what Victor said, it's worth noting that the
pass-by-reference overload may be slower, especially if the
function's definition has not yet been seen by the compiler at
the point of call. The problem is that the pass-by-reference
overload is allowed to retain a pointer to its argument (thus
restricting possible optimizations), whereas the pass-by-value
version is not.

In practice, the pass by reference is always implemented by
passing a pointer. Which means that the object referred to must
be locked in memory. For simple objects, which could otherwise
be in a register, this can make a significant difference; if a
function takes an int const&, and I pass it 43, the compiler
must create a temporary value (in memory) of type int,
iniitialize it with 43, then take the address of this variable
and pass it. If I just declare the function to take an int (or
an int const), the compiler can just pass the value immediately.

Within the called function, of course, the compiler must take
into account that the reference might be an alias; i.e. that
other references might refer to it, or that it might refer to a
global variable. This can lead to a lot more memory accesses
than otherwise.

In theory, the above should apply to any "smallish" type,
including non-polymorphic class types which only require one or
two words. In practice, I'm not aware of any compiler which
manages to optimize such objects into registers when they have
user defined constructors, so passing by const reference will
usually result in one copy less, with no other real effects, at
the call site. (The issues concerning aliasing still affect the
called function, however.) For this reason, one common
convention is to pass class types by reference to const, and
everything else by value.
 
J

James Kanze

Joel Spolsky advocates that all programmers should take
classes in writing. I am inclined to agree.

IMHO, that's putting the cart before the horse. You shouldn't
be allowed to learn programming until you can express yourself
clearly and concisely in your native language.

In this particular case, however, I'd make allowance for a
possible typo, rather than automatically assuming that the
poster didn't know or understand the difference. (I know that I
know the difference, but I'll bet that if you were to search all
of my postings, you'd find a couple of slip ups.) And of
course, there's also the possibility that English isn't the
poster's native language.
 
J

James Kanze

Right, although probably not "immediately" in the sense of an
immediate argument to the opcode. At least, if the function
definition has not been seen by the compiler at the point of
call, the int probably has to be pushed onto the stack.
That's still better than pushing a *pointer* to the int onto
the stack.

The int value has to be put where ever parameters are put. The
first five go into registers on my machine.
Where reasonable, I use traits classes to determine the
correct type to pass.

In templates, of course, you don't know whether T is a class
type or not, so you have to fudge. For the most part, people
seem to prefer const reference, on the grounds that non-class
types are fairly rare.

Other considerations also come into consideration. If the
function is going to modify the value (e.g. as with an
iterator), then pass by value often makes sense even for class
types, and in cases where there is an inversion of control,
there's no really adequate solution: const reference means that
the callback function must be const, non-const reference means
that you can't pass an rvalue, and value means that you've lost
identity. (The standard library uses value in such cases---if
you need identity, then you must add a level of indirection.)
 

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,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top