Topic: A use for const references?


Author: fjh@cs.mu.oz.au (Fergus Henderson)
Date: 1997/09/03
Raw View
Bill Wade <bill.wade@stoner.com> wrote:
 >struct foo1
 >{
 >  foo(int& ii):i(ii){}
 >  const int i;  // Non-static member
 >};
 >
 >void fuzz1(foo1&);
 >bool bar1(foo1& f)
 >{
 >  int o = f.i;
 >  fuzz1(f);
 >  return o == f.i;
 >}
 >
 >I believe that a compiler can optimize bar to always return true (avoid the
 >final comparison).  ...  Please correct me if I'm wrong.

I'm pretty sure that's correct.

 >Now consider
 >
 >struct foo2
 >{
 >  foo2(int& ii):i(ii){}
 >  int& i;
 >};
 >
 >void fuzz2(foo2&);
 >bool bar2(foo2& f)
 >{
 >  int* o = &f.i;
 >  fuzz2(f);
 >  return o == &f.i;
 >}
 >
 >I don't believe the compiler can optimize bar2 (at least if fuzz2 is in
 >another compilation unit).

Also correct.

This is an interesting difference between references and const pointers.

 >However if the reference were const (a const reference, not a reference to
 >const) the optimization could be reinstated.  In other words
 >
 >struct foo2
 >{
 >  foo2(int& ii):i(ii){}
 >  int& const i;
 >};
 >
 >would allow bar2() to avoid the final comparision.  Do I have this right?

Nope.  There's no such thing as a const reference, there are only
references to const.  See 8.3.2[decl.ref]/1.

 |   8.3.2  References                                            [dcl.ref]
 |
 | 1 ... Cv-qualified  refer-
 |   ences  are  ill-formed  except  when  the cv-qualifiers are introduced
 |   through the use of a typedef (_dcl.typedef_) or  of  a  template  type
 |   argument  (_temp.arg_),  in  which case the cv-qualifiers are ignored.

 >Now I'll try to sneak in a non comp.std.c++ question.  Does anyone know of
 >compilers which perform either or both of these optimizations?

I'd be surprised if there any compilers which performs this optimization.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Bill Wade" <bill.wade@stoner.com>
Date: 1997/08/19
Raw View
Consider the following:

struct foo1
{
  foo(int& ii):i(ii){}
  const int i;  // Non-static member
};

void fuzz1(foo1&);
bool bar1(foo1& f)
{
  int o = f.i;
  fuzz1(f);
  return o == f.i;
}

I believe that a compiler can optimize bar to always return true (avoid the
final comparison).  If fuzz modifies f.i using a cast the results are
undefined.  Likewise if fuzz destructs and reconstructs f: from 3.8.9:

 "Creating a new object at the storage location that a const object with
  static or automatic storage duration occupies or, at the storage loca-
  tion that such a const object used to occupy before its lifetime ended
  results in undefined behavior."

Since f.i is a const object, you get undefined behavior if you reconstruct
f in place.  I believe this means that the compiler can assume that fuzz.i
won't change its value.  Please correct me if I'm wrong.

Now consider

struct foo2
{
  foo2(int& ii):i(ii){}
  int& i;
};

void fuzz2(foo2&);
bool bar2(foo2& f)
{
  int* o = &f.i;
  fuzz2(f);
  return o == &f.i;
}

I don't believe the compiler can optimize bar2 (at least if fuzz2 is in
another compilation unit).  It is perfectly legal for fuzz2 destruct and
reconstruct its argument, possibly changing the value of (&f.i).
It isn't really necessary to pass f to fuzz2 for the problem to arise,
fuzz2 may have access to f through some other route (aliasing problem).
However if the reference were const (a const reference, not a reference to
const) the optimization could be reinstated.  In other words

struct foo2
{
  foo2(int& ii):i(ii){}
  int& const i;
};

would allow bar2() to avoid the final comparision.  Do I have this right?

Now I'll try to sneak in a non comp.std.c++ question.  Does anyone know of
compilers which perform either or both of these optimizations?  How about
compilers which do the foo2 optimization even if the reference is not
const?
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]