Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #9756 > unrolled thread

[n00b] Different ways of representing "address" arguments

Started by"Jarrick Chagma" <Jarrick.Chagma@your.mind.gmail.com>
First post2011-09-05 23:11 +1000
Last post2011-09-08 18:53 -0700
Articles 12 — 10 participants

Back to article view | Back to comp.lang.c++


Contents

  [n00b] Different ways of representing "address" arguments "Jarrick Chagma" <Jarrick.Chagma@your.mind.gmail.com> - 2011-09-05 23:11 +1000
    Re: Different ways of representing "address" arguments Saeed Amrollahi <amrollahi.saeed@gmail.com> - 2011-09-05 06:47 -0700
    Re: Different ways of representing "address" arguments gwowen <gwowen@gmail.com> - 2011-09-05 06:59 -0700
    Re: Different ways of representing "address" arguments Goran <goran.pusic@gmail.com> - 2011-09-05 23:57 -0700
      Re: Different ways of representing "address" arguments Paul <pchristor@yahoo.co.uk> - 2011-09-06 09:04 -0700
        Re: Different ways of representing "address" arguments "Thomas J. Gritzan" <phygon_antispam@gmx.de> - 2011-09-07 02:32 +0200
          Re: Different ways of representing "address" arguments "Paul" <pchristor@yahoo.co.uk> - 2011-09-09 01:20 +0100
        Re: Different ways of representing "address" arguments Goran <goran.pusic@gmail.com> - 2011-09-07 00:01 -0700
          Re: Different ways of representing "address" arguments Paul <pchristor@yahoo.co.uk> - 2011-09-07 05:09 -0700
    Re: [n00b] Different ways of representing "address" arguments Bart van Ingen Schenau <bart@ingen.ddns.info> - 2011-09-06 13:19 +0200
      Re: Different ways of representing "address" arguments James Kanze <james.kanze@gmail.com> - 2011-09-06 15:29 -0700
    Re: Different ways of representing "address" arguments Joshua Maurice <joshuamaurice@gmail.com> - 2011-09-08 18:53 -0700

#9756 — [n00b] Different ways of representing "address" arguments

From"Jarrick Chagma" <Jarrick.Chagma@your.mind.gmail.com>
Date2011-09-05 23:11 +1000
Subject[n00b] Different ways of representing "address" arguments
Message-ID<EpydnR4coofgV_nTnZ2dnUVZ_tednZ2d@westnet.com.au>
I am new to C++ and have a basic question.  What is the semantic difference 
between these two:

A) void foo(const int &i)
B) void foo(int *i)

AFAICT, both will result in the address of an integer argument being passed 
to foo() and in both cases the address cannot be modified.  Are there any 
differences other than that i will need to be dereferenced in (B)?  Which is 
preferred?

--
Regards,

Jarrick 

[toc] | [next] | [standalone]


#9757 — Re: Different ways of representing "address" arguments

FromSaeed Amrollahi <amrollahi.saeed@gmail.com>
Date2011-09-05 06:47 -0700
SubjectRe: Different ways of representing "address" arguments
Message-ID<5eb32c5f-5538-4ca3-b656-948cac5d6a6e@r21g2000yqr.googlegroups.com>
In reply to#9756
On Sep 5, 4:11 pm, "Jarrick Chagma"
<Jarrick.Cha...@your.mind.gmail.com> wrote:
> I am new to C++ and have a basic question.  What is the semantic difference
> between these two:
>
> A) void foo(const int &i)
> B) void foo(int *i)
>
They are two different approaches to reference semantics in C and C++
in B, you pass the address of and object to function foo and likely
you want to change the value of the variable that i points to.
It's uses in both C and C++.
in A, you pass a reference to constant int (read from right to left)
so you pass the actual object not a copy of it.
It's uses in C++.
Please note, A and B aren't exactly equivalent. The following are
equivalent:
 A) void foo(int& i);
 B) void foo(int* i);
or
 A) void bar(const int& i);
 B) void bar(const int* i);
> AFAICT, both will result in the address of an integer argument being passed
> to foo() and in both cases the address cannot be modified.
From the point of implementation view, a reference is implemented
using constant
pointers.
 Are there any
> differences other than that i will need to be dereferenced in (B)?  Which is
> preferred?
>
In C++, we prefer references over pointers.Use references whenever
possible,
and use pointers when you have to.
for further information see:
  - Scott Meyers. More Effective C++, Item 1
  - http://www.parashift.com/c++-faq/references.html

> --
> Regards,
>
> Jarrick

HTH,
  -- Saeed Amrollahi

[toc] | [prev] | [next] | [standalone]


#9758 — Re: Different ways of representing "address" arguments

Fromgwowen <gwowen@gmail.com>
Date2011-09-05 06:59 -0700
SubjectRe: Different ways of representing "address" arguments
Message-ID<7c1639f8-ae0e-47df-a937-4a5cbfcf56aa@a13g2000yqd.googlegroups.com>
In reply to#9756
On Sep 5, 2:11 pm, "Jarrick Chagma"
<Jarrick.Cha...@your.mind.gmail.com> wrote:
> I am new to C++ and have a basic question.  What is the semantic difference
> between these two:
>
> A) void foo(const int &i)
> B) void foo(int *i)
>
> AFAICT, both will result in the address of an integer argument being passed
> to foo() and in both cases the address cannot be modified.  

That's not quite right.  The argument to (A) is a reference to a
constant object - its the object itself that cannot be modified.
References themselves can never be modified/reseated, just as they can
never be NULL (although they can refer to objects that no longer
exist).

Similarly, "const int *i" is a pointer to a constant object, and "int
* const i" is a constant pointer to a modifiable object.

> Which is preferred?

In the loosest sense -- and noting that B) would be foo(const int *i)
for the semantics to be fundamentally the same -- use B if C-
compatibility is required, or if a NULL argument makes sense.  Use A
otherwise.

[toc] | [prev] | [next] | [standalone]


#9779 — Re: Different ways of representing "address" arguments

FromGoran <goran.pusic@gmail.com>
Date2011-09-05 23:57 -0700
SubjectRe: Different ways of representing "address" arguments
Message-ID<967b9c68-65e0-4587-ba69-a296472cd503@u6g2000yqa.googlegroups.com>
In reply to#9756
On Sep 5, 3:11 pm, "Jarrick Chagma"
<Jarrick.Cha...@your.mind.gmail.com> wrote:
> I am new to C++ and have a basic question.  What is the semantic difference
> between these two:
>
> A) void foo(const int &i)
> B) void foo(int *i)
>
> AFAICT, both will result in the address of an integer argument being passed
> to foo()
> and in both cases the address cannot be modified.  Are there any
> differences other than that i will need to be dereferenced in (B)?  Which is
> preferred?

IMHO, if you see a pointer in a well-designed C++ code, it means
there's a program state where said pointer can be null. That also
means dealing with said null.

A reference, however, is never "null", there's no such thing except in
BROKEN code (e.g. a reference was created from NULL pointer).

Now, note that references in C++ give access to a parameter passing by
references. Not all languages have that. E.g. Pascal have it (look for
"var" in function/procedure parameter list), as well as C# (look for
"ref" and "out"). Java, and more notably C, do not have pass-by-
reference. In C, the only way to pass-by-reference is to use a
pointer. But a pointer is like an "optional reference" (NULL kinda
means "here's a reference to an absent variable"). Consequence of
that, and because a NULL pointer is legal code, C code tends to be
fraught with checks for NULL where there should be none, and fraught
with future danger to pass NULL where you shouldn't, exactly because
there's no possibility to be explicit about intended pass-by-
reference.

Finally, some people argue against use of references for pass-by-ref
in C++ code, because at the call site (foo(some_int)), you don't see
that a given value can be changed, whereas, if you use a pointer, that
ain't the case (foo(*some_int)), because that "*" stands out like a
sore thumb. However, in good C code, if a parameter passed in by a
pointer should not change inside a function, it should be declared
"const", and then, you again don't really see whether it will be
changed or not, you can only guess that it might. In that respect, C#
does the right thing IMO, by requiring use of "ref" and "out" at a
call site as well as in the declaration.

To cut the long story short: when in Rome, do as Romans do. Use
reference for reference parameters, pointers for "optional reference"
parameters. And yes, in common implementations, "under the hood", the
two are the same thing.

Goran.

[toc] | [prev] | [next] | [standalone]


#9808 — Re: Different ways of representing "address" arguments

FromPaul <pchristor@yahoo.co.uk>
Date2011-09-06 09:04 -0700
SubjectRe: Different ways of representing "address" arguments
Message-ID<e3f0ae81-ed39-402e-a93a-a327b071963c@r17g2000yqa.googlegroups.com>
In reply to#9779
On Sep 6, 7:57 am, Goran <goran.pu...@gmail.com> wrote:
> On Sep 5, 3:11 pm, "Jarrick Chagma"
>
> <Jarrick.Cha...@your.mind.gmail.com> wrote:
> > I am new to C++ and have a basic question.  What is the semantic difference
> > between these two:
>
> > A) void foo(const int &i)
> > B) void foo(int *i)
>
> > AFAICT, both will result in the address of an integer argument being passed
> > to foo()
> > and in both cases the address cannot be modified.  Are there any
> > differences other than that i will need to be dereferenced in (B)?  Which is
> > preferred?
>
> IMHO, if you see a pointer in a well-designed C++ code, it means
> there's a program state where said pointer can be null. That also
> means dealing with said null.
>
There is also the case where polymorphic behavour is expected.
The function may take a Shape pointer parameter type, where a Circle
or a Polygon is expected.

[toc] | [prev] | [next] | [standalone]


#9857 — Re: Different ways of representing "address" arguments

From"Thomas J. Gritzan" <phygon_antispam@gmx.de>
Date2011-09-07 02:32 +0200
SubjectRe: Different ways of representing "address" arguments
Message-ID<j46e3v$1r9$1@newsreader4.netcologne.de>
In reply to#9808
Am 06.09.2011 18:04, schrieb Paul:
> On Sep 6, 7:57 am, Goran<goran.pu...@gmail.com>  wrote:
>> On Sep 5, 3:11 pm, "Jarrick Chagma"
>>
>> <Jarrick.Cha...@your.mind.gmail.com>  wrote:
>>> I am new to C++ and have a basic question.  What is the semantic difference
>>> between these two:
>>
>>> A) void foo(const int&i)
>>> B) void foo(int *i)

The const in A) applies to the referred to integer. In A) you cannot 
change the value, while in B) you can change the pointed to value and 
the pointer itself.

(well, you can only change the local copy of the pointer, but not the 
pointer in the calling function.)

>>> AFAICT, both will result in the address of an integer argument being passed
>>> to foo()
>>> and in both cases the address cannot be modified.  Are there any
>>> differences other than that i will need to be dereferenced in (B)?  Which is
>>> preferred?

Prefer references unless you need pointer semantics. Prefer const unless 
you need to modify.

>> IMHO, if you see a pointer in a well-designed C++ code, it means
>> there's a program state where said pointer can be null. That also
>> means dealing with said null.
>>
> There is also the case where polymorphic behavour is expected.
> The function may take a Shape pointer parameter type, where a Circle
> or a Polygon is expected.

Goran wanted to point out a difference between pointers and references.

A reference cannot (legally) be null like a pointer, but polymorphic 
behaviour works equally with references and pointers.

-- 
Thomas

[toc] | [prev] | [next] | [standalone]


#9948 — Re: Different ways of representing "address" arguments

From"Paul" <pchristor@yahoo.co.uk>
Date2011-09-09 01:20 +0100
SubjectRe: Different ways of representing "address" arguments
Message-ID<j4bm57$l1f$1@adenine.netfront.net>
In reply to#9857
"Thomas J. Gritzan" <phygon_antispam@gmx.de> wrote in message 
news:j46e3v$1r9$1@newsreader4.netcologne.de...
> Am 06.09.2011 18:04, schrieb Paul:
>> On Sep 6, 7:57 am, Goran<goran.pu...@gmail.com>  wrote:
>>> On Sep 5, 3:11 pm, "Jarrick Chagma"
>>>
>>> <Jarrick.Cha...@your.mind.gmail.com>  wrote:
>>>> I am new to C++ and have a basic question.  What is the semantic 
>>>> difference
>>>> between these two:
>>>
>>>> A) void foo(const int&i)
>>>> B) void foo(int *i)
>
> The const in A) applies to the referred to integer. In A) you cannot 
> change the value, while in B) you can change the pointed to value and the 
> pointer itself.
>
> (well, you can only change the local copy of the pointer, but not the 
> pointer in the calling function.)
>
>>>> AFAICT, both will result in the address of an integer argument being 
>>>> passed
>>>> to foo()
>>>> and in both cases the address cannot be modified.  Are there any
>>>> differences other than that i will need to be dereferenced in (B)? 
>>>> Which is
>>>> preferred?
>
> Prefer references unless you need pointer semantics. Prefer const unless 
> you need to modify.
>
>>> IMHO, if you see a pointer in a well-designed C++ code, it means
>>> there's a program state where said pointer can be null. That also
>>> means dealing with said null.
>>>
>> There is also the case where polymorphic behavour is expected.
>> The function may take a Shape pointer parameter type, where a Circle
>> or a Polygon is expected.
>
> Goran wanted to point out a difference between pointers and references.
>
> A reference cannot (legally) be null like a pointer, but polymorphic 
> behaviour works equally with references and pointers.
>
Yes I realise he was pointing out the difference between pointers and 
references. I was mainly responding to what he said about seeing a pointer 
in code means there will be a null state someplace, which is actually what I 
usually think myself. I was looking for a senario where this assumption is 
not always a prudent assumption. As you correctly pointed out my 
polymorphism example was not an ideal scenario as I was overlooking the fact 
that this can also be done using references.

Apart from the obvious scenario of re-allocating a different object to the 
pointer, and the benefits of having a possible null. There is another 
scenario where it may be beneficial to prefer a pointer over a reference 
thus it is not always prudent to assume the pointer may be null. That is 
when the argument is a pointer to an array. 


--- Posted via news://freenews.netfront.net/ - Complaints to news@netfront.net ---

[toc] | [prev] | [next] | [standalone]


#9867 — Re: Different ways of representing "address" arguments

FromGoran <goran.pusic@gmail.com>
Date2011-09-07 00:01 -0700
SubjectRe: Different ways of representing "address" arguments
Message-ID<f2ec119d-443f-4271-903f-6fa1b815f04b@l2g2000vbn.googlegroups.com>
In reply to#9808
On Sep 6, 6:04 pm, Paul <pchris...@yahoo.co.uk> wrote:
> On Sep 6, 7:57 am, Goran <goran.pu...@gmail.com> wrote:
>
>
>
>
>
>
>
> > On Sep 5, 3:11 pm, "Jarrick Chagma"
>
> > <Jarrick.Cha...@your.mind.gmail.com> wrote:
> > > I am new to C++ and have a basic question.  What is the semantic difference
> > > between these two:
>
> > > A) void foo(const int &i)
> > > B) void foo(int *i)
>
> > > AFAICT, both will result in the address of an integer argument being passed
> > > to foo()
> > > and in both cases the address cannot be modified.  Are there any
> > > differences other than that i will need to be dereferenced in (B)?  Which is
> > > preferred?
>
> > IMHO, if you see a pointer in a well-designed C++ code, it means
> > there's a program state where said pointer can be null. That also
> > means dealing with said null.
>
> There is also the case where polymorphic behavour is expected.
> The function may take a Shape pointer parameter type, where a Circle
> or a Polygon is expected.

References exhibit polymorphic behavior just like pointers. Two issues
are completely orthogonal. E.g.

class Shape { virtual void Draw() = 0 };
class Circle { virtual void Draw() { cout << "c"; };
class Rectangle { virtual void Draw() { cout << "r"; };

void f(Shape& s)
{
 s.Draw();
}
Circle c;
Rectangle r;
f(c);
f(r);

prints "c" and "r". You don't _need_ pointers there.

Goran.

P.S. Are you the guy who have been insulting me before, saying I don'
know my stuff? The above is pretty basic C++. The nerve of some
people...

[toc] | [prev] | [next] | [standalone]


#9894 — Re: Different ways of representing "address" arguments

FromPaul <pchristor@yahoo.co.uk>
Date2011-09-07 05:09 -0700
SubjectRe: Different ways of representing "address" arguments
Message-ID<d54405d0-7164-4d34-966d-70e7a0a7e9da@d18g2000yqm.googlegroups.com>
In reply to#9867
On Sep 7, 8:01 am, Goran <goran.pu...@gmail.com> wrote:
> On Sep 6, 6:04 pm, Paul <pchris...@yahoo.co.uk> wrote:
>
>
>
>
>
> > On Sep 6, 7:57 am, Goran <goran.pu...@gmail.com> wrote:
>
> > > On Sep 5, 3:11 pm, "Jarrick Chagma"
>
> > > <Jarrick.Cha...@your.mind.gmail.com> wrote:
> > > > I am new to C++ and have a basic question.  What is the semantic difference
> > > > between these two:
>
> > > > A) void foo(const int &i)
> > > > B) void foo(int *i)
>
> > > > AFAICT, both will result in the address of an integer argument being passed
> > > > to foo()
> > > > and in both cases the address cannot be modified.  Are there any
> > > > differences other than that i will need to be dereferenced in (B)?  Which is
> > > > preferred?
>
> > > IMHO, if you see a pointer in a well-designed C++ code, it means
> > > there's a program state where said pointer can be null. That also
> > > means dealing with said null.
>
> > There is also the case where polymorphic behavour is expected.
> > The function may take a Shape pointer parameter type, where a Circle
> > or a Polygon is expected.
>
> References exhibit polymorphic behavior just like pointers. Two issues
> are completely orthogonal. E.g.
>
> class Shape { virtual void Draw() = 0 };
> class Circle { virtual void Draw() { cout << "c"; };
> class Rectangle { virtual void Draw() { cout << "r"; };
>
> void f(Shape& s)
> {
>  s.Draw();}
>
> Circle c;
> Rectangle r;
> f(c);
> f(r);
>
> prints "c" and "r". You don't _need_ pointers there.

Ah ok I forgot you can do that.

>
> Goran.
>
> P.S. Are you the guy who have been insulting me before, saying I don'
> know my stuff? The above is pretty basic C++. The nerve of some
> people...- Hide quoted text -

Dunno when I am supposed to have insulted you. Perhaps if I've said
"you don't know your stuff" you have made some silly argument that
made that appear to be the case. I wouldn't take that as an insult its
only a small gibe.
Please link the message you are talking about.

> - Show quoted text -

[toc] | [prev] | [next] | [standalone]


#9798

FromBart van Ingen Schenau <bart@ingen.ddns.info>
Date2011-09-06 13:19 +0200
Message-ID<j44vjv$6pp$1@localhost.localdomain>
In reply to#9756
Jarrick Chagma Wrote:

> I am new to C++ and have a basic question.  What is the semantic
> difference
> 
> between these two:
> 
> A) void foo(const int &i)
> B) void foo(int *i)
> 
> AFAICT, both will result in the address of an integer argument being
> passed to foo() and in both cases the address cannot be modified.

This is not neccesarilly true. In version A, the name 'i' inside foo is an
alias to the argument passed to foo in the call. The most common way for a
compiler to implement these semantics is by actually passing the address of
the argument, but there is no requirement to do it that way.

> Are there any differences other than that i will need to be 
> dereferenced in (B)?  Which is preferred?

One major difference between A and B, as they are declared now, is that in A
the object that 'i' refers to can not be changed from within foo, while in B
the object that 'i' points at *can* be changed.
For indicating which is preferred, lets look at all the ways you can pass
arguments:

- By value: void foo(int i): This is preferred when passing (small)
objects/values to a function, where the function is not expected to change
the passed object.
- By const reference: void foo(const int& i): This is preferred when passing
large(-ish) objects/values to a function, where the function is not supposed
to change the passed object.
- By pointer: void foo(const int* i) or void foo(int* i): This is preferred
when you need a mechanism to indicate the absence of a value. Use the first
variant if the function is not supposed to update the argument.
- By non-const reference: void foo(int& i): This is preferred when foo is
supposed to update the argument and the argument is mandatory.

> 
> --
> Regards,
> 
> Jarrick
> 
Bart v Ingen Schenau

[toc] | [prev] | [next] | [standalone]


#9837 — Re: Different ways of representing "address" arguments

FromJames Kanze <james.kanze@gmail.com>
Date2011-09-06 15:29 -0700
SubjectRe: Different ways of representing "address" arguments
Message-ID<c1781dea-ed43-49d5-8e86-f1923d57a209@a12g2000yqi.googlegroups.com>
In reply to#9798
On Sep 6, 12:19 pm, Bart van Ingen Schenau <b...@ingen.ddns.info>
wrote:
> Jarrick Chagma Wrote:

> > I am new to C++ and have a basic question.  What is the semantic
> > difference

> > between these two:

> > A) void foo(const int &i)
> > B) void foo(int *i)

> > AFAICT, both will result in the address of an integer argument being
> > passed to foo() and in both cases the address cannot be modified.

> This is not neccesarilly true. In version A, the name 'i' inside foo is an
> alias to the argument passed to foo in the call. The most common way for a
> compiler to implement these semantics is by actually passing the address of
> the argument, but there is no requirement to do it that way.

> > Are there any differences other than that i will need to be
> > dereferenced in (B)?  Which is preferred?

> One major difference between A and B, as they are declared
> now, is that in A the object that 'i' refers to can not be
> changed from within foo, while in B the object that 'i' points
> at *can* be changed.

Another major difference is that you can pass a temporary (the
results of an expression or a function) to A; you can't to B.

And yet another difference is that you can pass a null pointer
to B; you can't to A.

Not to mention the different syntax at the call site.

All things taken together, there are probably more differences
than similarities.

--
James Kanze

[toc] | [prev] | [next] | [standalone]


#9949 — Re: Different ways of representing "address" arguments

FromJoshua Maurice <joshuamaurice@gmail.com>
Date2011-09-08 18:53 -0700
SubjectRe: Different ways of representing "address" arguments
Message-ID<3d257d87-ac99-4c0c-b59e-37a7c05634d9@e20g2000prn.googlegroups.com>
In reply to#9756
On Sep 5, 6:11 am, "Jarrick Chagma"
<Jarrick.Cha...@your.mind.gmail.com> wrote:
> I am new to C++ and have a basic question.  What is the semantic difference
> between these two:
>
> A) void foo(const int &i)
> B) void foo(int *i)
>
> AFAICT, both will result in the address of an integer argument being passed
> to foo() and in both cases the address cannot be modified.  Are there any
> differences other than that i will need to be dereferenced in (B)?  Which is
> preferred?

That is an incorrect description of what's going on. Using your loose
terminology,
  void foo(int & i);
"passes the address of an int object, and the address cannot be
modified". Once you create a reference, it cannot be changed to refer
to something else.

The following means something different.
  void foo(const int & i)
The proper way to read the argument type is "a reference to a const
int". References are always unchangeable, but what it refers to can be
changeable.

  int &
The reference is not changeable to "point" to another object. However,
you can change the refered-to object.

  const int &
  int const &
The reference is not changeable to "point" to another object. Also,
you cannot change the refered-to object.

  int *
You can change which object the pointer points to. Also, you can
change the pointed-to object.

  const int *
  int const *
You can change which object the pointer points to. However, you cannot
change the pointed-to object.

  int * const
You cannot change which object the pointer points to. However, you can
change the pointed-to object.

Your original function
  void foo(int * );
takes a pointer by value. The caller's argument pointer object will
not be changed. However, the caller's pointed-to object can be
changed.

With
  void foo(const int & );
This takes a reference to an int object, specifically a reference to
const int. The caller's int object will not be changed (unless
const_cast).

The proper things to compare are:
  void foo(int & );
  void foo(int * );
Here, on nearly any implementation, they will be implemented with the
same assembly. To finally answer your question, the difference is
largely syntactic sugar and convention, and I won't repeat most of
what they said here. Do note as explained else-thread that it's
undefined behavior to create a "null" reference, so the body of "void
foo( int & )" would not have to deal with the possibility of null,
whereas "void foo(int * )" can legitimately be given a null argument.
But of course, you could document the function as taking only non-
nulls, and put the burden on the caller to ensure only non-null
pointers are passed to it. Convention.

PS: This is assuming that we're following basic const correctness.
With no const correctness, or with const_cast-ing, then some of what I
said above does not apply. Do note that any attempt to make a
reference point to a different object is still undefined behavior.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web