Topic: Accessing Constant Integers


Author: Andy Sawyer <andys@thone.demon.co.uk>
Date: 1995/05/30
Raw View
In article <3qc06v$16j@gabi.gabi-soft.fr> kanze@gabi-soft.fr
       "J. Kanze" writes:

> Stan Friesen (swf@elsegundoca.ncr.com) wrote:
> |> The implementation [of auto_ptr] is almost trivial:
>
> |> template class auto_ptr<class X>
> |>   class auto_ptr
> |>     {
> |>     public:
>
> |>      X *reset(X *p = 0)
> |>          {
> |>              delete _ptr;
> |>              _ptr = p;
> |>          };
>
> Isn't something missing here?
>
> What should `reset' return?  (I suspect its parameter.  I don't see any
> advantage in returning a deleted pointer; in fact, I think it would be
> undefined behavior.)
>
 I rather thought that reset would replace the pointer, without deleteing
the object so:

   template<class X>
   class auto_ptr {
   private:
      X *m_Ptr;
   public:
      X *reset( X *p = 0 )
      {
        X *ptmp = m_Ptr;
        m_Ptr = p;
        return ptmp;
      }

  // etc...

--
* Andy Sawyer ** e-mail:andys@thone.demon.co.uk ** Compu$erve:100432,1713 **
 The opinions expressed above are my own, but you are granted the right to
 use and freely distribute them. I accept no responsibility for any injury,
 harm or damage arising from their use.                --   The Management.





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/05/29
Raw View
Stan Friesen (swf@elsegundoca.ncr.com) wrote:
|> The implementation [of auto_ptr] is almost trivial:

|> template class auto_ptr<class X>
|>   class auto_ptr
|>     {
|>     public:

|>  X *reset(X *p = 0)
|>      {
|>   delete _ptr;
|>   _ptr = p;
|>      };

Isn't something missing here?

What should `reset' return?  (I suspect its parameter.  I don't see any
advantage in returning a deleted pointer; in fact, I think it would be
undefined behavior.)

|>     private:
|>  X *_ptr;
|>     }
--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
                             --Beratung in industrieller Datenverarbeitung





Author: BrianS@pbcomputing.com (Brian Stern)
Date: 1995/05/25
Raw View
In article <D93oov.6GK@actrix.gen.nz>, reycri@atlantis.actrix.gen.nz
(Reynaldo Crisostomo) wrote:

< In article <9514218.28385@mulga.cs.mu.oz.au>,
< Fergus Henderson <fjh@munta.cs.mu.OZ.AU> wrote:
< > >bartley@pact.srf.ac.uk (Mike Bartley) wrote:
< > >>I am interested in what people think this code should do:
< > >>
< > >>void main()
< >
< > Insert usual complaint about main() not returning an int..
< >
< > >>{
< > >>  const int j = 0;
< > >>  const int *pic = &j;
<
< Is this legal? I would have thought that j is not an lvalue and hence,
< not addressable. Or is that only for consts defined outside any function?
<

It's legal.  But notice that you can only assign the address of a const
int to a pointer to const int.  This means that without typecasting you
can't modify the const int.  And as has been mentioned, attempting to do
this results in undefined behavior.

< > >>  int *pi;
< > >>
< > >>  pi = (int *)pic;
< > >>  *pi = 1;
< > >>}
< >
< > The code has undefined behaviour.
< >
< Rey Crisostomo
< --
< Rey Crisostomo
< reycri@actrix.gen.nz
< Wellington, New Zealand

____________________________________________________________________
Brian  Stern  {:-{)}                          BrianS@pbcomputing.com
Toolbox commando and Menu bard.             Will FlushCache for Cash





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/05/26
Raw View
reycri@atlantis.actrix.gen.nz (Reynaldo Crisostomo) writes:

>Fergus Henderson <fjh@munta.cs.mu.OZ.AU> wrote:
>> >bartley@pact.srf.ac.uk (Mike Bartley) wrote:
>> >>{
>> >>  const int j = 0;
>> >>  const int *pic = &j;
>
>Is this legal? I would have thought that j is not an lvalue and hence,
>not addressable. Or is that only for consts defined outside any function?

Yes, it is legal.  `j' is a non-modifiable lvalue.
It would also be legal outside of any function.

--
Fergus Henderson                       | I'll forgive even GNU emacs as
fjh@cs.mu.oz.au                        | long as gcc is available ;-)
http://www.cs.mu.oz.au/~fjh            |             - Linus Torvalds





Author: swf@elsegundoca.ncr.com (Stan Friesen)
Date: 1995/05/26
Raw View
In article <3pr54s$opu@engnews2.Eng.Sun.COM>, clamage@Eng.Sun.COM (Steve Clamage) writes:
|>
|> Of course it is preferable! Why assign when you can initialize?
|>
|> The post that started the discussion involved using 'new' to initialize
|> a pointer, and not knowing whether the initialization had taken place
|> due to the possibility of an earlier exception. In that case you either
|> delete an uninitialized pointer, or have a memory leak.

The *real* solution is to use an auto_ptr<> for the owner of an object
being new'd.  Then you don't have to worry about whether it was initialized
or not, the language will take care of it for you.

The implementation is almost trivial:

template class auto_ptr<class X>
  class auto_ptr
    {
    public:
 auto_ptr(X *p = 0) { _ptr = p; };
 auto_ptr(auto_ptr &a) { _ptr = a.release(); };
 void operator =(auto_ptr &a) { reset(a.release()); };
 ~auto_ptr() { delete _ptr; };

 X *get() const { return _ptr; };
 X& operator *() const { return *get(); };
 X *operator->() const { return get(); };

 X *release()
     {
  X *tmp = _ptr;
  _ptr = NULL;
  return tmp;
     };

 X *reset(X *p = 0)
     {
  delete _ptr;
  _ptr = p;
     };

    private:
 X *_ptr;
    }

There, that implements it, as specified in the standard.

AND it is efficient - it is all inline.

--
swf@elsegundoca.attgis.com  sarima@netcom.com

The peace of God be with you.





Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/05/28
Raw View
In article <damian.801111295@bruce.cs.monash.edu.au>,
Damian Conway <damian@cs.monash.edu.au> wrote:
>
>Which would seem to mean that the following idiom (recently suggested by a
>highly respected contributer :-) is suspect:
>
> class Vector3D
> {
> public:
>  const double magnitude = 0;
>
>  Vector3D(double x, double y, double z)
>  {
>   const_cast<double&>(magnitude) = sqrt(x*x+y*y+z*z);
>  }
> }
>
>Would it not?

 Yes. In this case one can -- and should -- write

 Vector3D( .. ) : magnitude( sqrt( ..) ) {}

instead. However you CANNOT do that if the variable mentioned
is an aggregate. In particular

 arrays of types without a default constructor
 const aggreagtes

CANNOT be initialised in clases. Fixing this is on the Australian
National Body issues list  -- we required it be investigated
without suggesting a solution. The Committee has chosen
to respond by refusing to do anything -- at least without
a proposal being presented.

I propose that the USUAL syntax for initialisation be permitted
in mem-initialisers, that is:

 X() : a(1), // allowed now
  b=1, // not permitted now
  c= {1,2} // not permitted now
 {}

As fas as I can see this fixes the problem without inventing
ANY new semantics or syntax (just recycling the existing
one in a context where it should have been permitted in
the first place).


--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189





Author: reycri@atlantis.actrix.gen.nz (Reynaldo Crisostomo)
Date: 1995/05/24
Raw View
In article <9514218.28385@mulga.cs.mu.oz.au>,
Fergus Henderson <fjh@munta.cs.mu.OZ.AU> wrote:
> >bartley@pact.srf.ac.uk (Mike Bartley) wrote:
> >>I am interested in what people think this code should do:
> >>
> >>void main()
>
> Insert usual complaint about main() not returning an int..
>
> >>{
> >>  const int j = 0;
> >>  const int *pic = &j;

Is this legal? I would have thought that j is not an lvalue and hence,
not addressable. Or is that only for consts defined outside any function?

> >>  int *pi;
> >>
> >>  pi = (int *)pic;
> >>  *pi = 1;
> >>}
>
> The code has undefined behaviour.
>
> >>I have tried it on Borland C++ (3.1) and g++. Both compiled.
> >>In Borland the last line had NO effect.
> >>In g++ the last line did change j.
>
> They're both correct.
>
> Robert C. Martin <rmartin@oma.com> writes:
>
> >I am not sure, but I think the standard has changed this now, and that
> >the above code *should* change j.
>
> Nope, the behaviour is undefined, because the code attempts to modify a
> const object (that is, an object which was defined as const).
> Reference: 7.1.5.1/4.
>
> --
> Fergus Henderson                       | I'll forgive even GNU emacs as
> fjh@cs.mu.oz.au                        | long as gcc is available ;-)
> http://www.cs.mu.oz.au/~fjh            |             - Linus Torvalds

Rey Crisostomo
--
Rey Crisostomo
reycri@actrix.gen.nz
Wellington, New Zealand






Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/05/22
Raw View
>bartley@pact.srf.ac.uk (Mike Bartley) wrote:
>>I am interested in what people think this code should do:
>>
>>void main()

Insert usual complaint about main() not returning an int..

>>{
>>  const int j = 0;
>>  const int *pic = &j;
>>  int *pi;
>>
>>  pi = (int *)pic;
>>  *pi = 1;
>>}

The code has undefined behaviour.

>>I have tried it on Borland C++ (3.1) and g++. Both compiled.
>>In Borland the last line had NO effect.
>>In g++ the last line did change j.

They're both correct.

Robert C. Martin <rmartin@oma.com> writes:

>I am not sure, but I think the standard has changed this now, and that
>the above code *should* change j.

Nope, the behaviour is undefined, because the code attempts to modify a
const object (that is, an object which was defined as const).
Reference: 7.1.5.1/4.

--
Fergus Henderson                       | I'll forgive even GNU emacs as
fjh@cs.mu.oz.au                        | long as gcc is available ;-)
http://www.cs.mu.oz.au/~fjh            |             - Linus Torvalds





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/05/22
Raw View
damian@cs.monash.edu.au (Damian Conway) writes:

>>From 7.1.5.1, cv-qualifiers:
>
>>"Except that any class member declared mutable (7.1.1) can be modified,
>>any attempt to modify a const object during its lifetime (3.8) results
>>in undefined behavior."
>
>Which would seem to mean that the following idiom (recently suggested by a
>highly respected contributer :-) is suspect:
>
> class Vector3D
> {
> public:
>  const double magnitude = 0;
>
>  Vector3D(double x, double y, double z)
>  {
>   const_cast<double&>(magnitude) = sqrt(x*x+y*y+z*z);
>  }
> }
>
>Would it not?

Yes, it is certainly suspect - it has undefined behaviour, IMHO,
precisely because of the quoted paragraph from 7.1.5.1.

--
Fergus Henderson                       | I'll forgive even GNU emacs as
fjh@cs.mu.oz.au                        | long as gcc is available ;-)
http://www.cs.mu.oz.au/~fjh            |             - Linus Torvalds





Author: damian@cs.monash.edu.au (Damian Conway)
Date: 1995/05/22
Raw View
In <3pj1iq$7us@engnews2.Eng.Sun.COM> clamage@Eng.Sun.COM (Steve Clamage) writes:

>From 7.1.5.1, cv-qualifiers:

>"Except that any class member declared mutable (7.1.1) can be modified,
>any attempt to modify a const object during its lifetime (3.8) results
>in undefined behavior."

Which would seem to mean that the following idiom (recently suggested by a
highly respected contributer :-) is suspect:

 class Vector3D
 {
 public:
  const double magnitude = 0;

  Vector3D(double x, double y, double z)
  {
   const_cast<double&>(magnitude) = sqrt(x*x+y*y+z*z);
  }
 }

Would it not?

damian
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  who: Damian Conway                 email: damian@bruce.cs.monash.edu.au
where: Dept. Computer Science        phone: +61-3-565-5184
       Monash University               fax: +61-3-565-5146
       Clayton 3168                  quote: "A pessimist is never disappointed."
       AUSTRALIA





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/05/22
Raw View
In article 801111295@bruce.cs.monash.edu.au, damian@cs.monash.edu.au (Damian Conway) writes:
>In <3pj1iq$7us@engnews2.Eng.Sun.COM> clamage@Eng.Sun.COM (Steve Clamage) writes:
>
>>From 7.1.5.1, cv-qualifiers:
>
>>"Except that any class member declared mutable (7.1.1) can be modified,
>>any attempt to modify a const object during its lifetime (3.8) results
>>in undefined behavior."
>
>Which would seem to mean that the following idiom (recently suggested by a
>highly respected contributer :-) is suspect:
>
> class Vector3D
> {
> public:
>  const double magnitude = 0;
>
>  Vector3D(double x, double y, double z)
>  {
>   const_cast<double&>(magnitude) = sqrt(x*x+y*y+z*z);
>  }
> }

That code should not compile. Only a static data member of integral type
may have an initializer. "magnitude" is neither static nor integral.

Let me guess what you might have meant:
 class IntVector {
 public:
  static const int magnitude = 0;
  IntVector(int mag) {
   const_cast<int&>(magnitude) = mag;
  }
 };
The revised example has undefined results, since IntVector::magnitude is
a const object in its own right. For example, the compiler might choose to
put it in non-writeable memory.

I posted an example more along these lines:

 class Vector3D {
  const double magnitude; // not a static member
 public:
  Vector3D(double x, double y, double z) : magnitude(0.0)
  {
   const_cast<double&>(magnitude) = sqrt(...);
  }
 };

I believe this practice is safe and portable. Even when constructing a
const object, the (entire) object cannot in general be made non-writable
until the constructor has completed.

That leaves the possibility of individual non-static data members being
made non-writable within a writeable object. I don't believe that concept
is addressed by the draft standard. (Perhaps someone could correct me on
that point.)
---
Steve Clamage, stephen.clamage@eng.sun.com







Author: Andy Sawyer <andys@thone.demon.co.uk>
Date: 1995/05/22
Raw View
In article <3pqeit$jo4@engnews2.Eng.Sun.COM>
           clamage@Eng.Sun.COM "Steve Clamage" writes:


> I posted an example more along these lines:
>
>         class Vector3D {
>                 const double magnitude; // not a static member
>         public:
>                 Vector3D(double x, double y, double z) : magnitude(0.0)
>                 {
>                         const_cast<double&>(magnitude) = sqrt(...);
>                 }
>         };
>
> I believe this practice is safe and portable. Even when constructing a
> const object, the (entire) object cannot in general be made non-writable
> until the constructor has completed.
>

 A (possibly) preferable construct (IMHO of course!) would be:


   class Vector3D {
        const double magnitude; // not a static member
   public:
        Vector3D(double x, double y, double z)
           : magnitude( sqrt( x * x + y * y + z * z ) )
         {
         }
   };

 Thus the const memmber is initialised before the constructor body proper.
Comments, anyone?

--
* Andy Sawyer ** e-mail:andys@thone.demon.co.uk ** Compu$erve:100432,1713 **
 The opinions expressed above are my own, but you are granted the right to
 use and freely distribute them. I accept no responsibility for any injury,
 harm or damage arising from their use.                --   The Management.





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/05/22
Raw View
In article 801179071snz@thone.demon.co.uk, Andy Sawyer <andys@thone.demon.co.uk> writes:
>In article <3pqeit$jo4@engnews2.Eng.Sun.COM>
>           clamage@Eng.Sun.COM "Steve Clamage" writes:
>
>
>> I posted an example more along these lines:
>>
>>         class Vector3D {
>>                 const double magnitude; // not a static member
>>         public:
>>                 Vector3D(double x, double y, double z) : magnitude(0.0)
>>                 {
>>                         const_cast<double&>(magnitude) = sqrt(...);
>>                 }
>>         };
>>
>> I believe this practice is safe and portable. Even when constructing a
>> const object, the (entire) object cannot in general be made non-writable
>> until the constructor has completed.
>>
>
> A (possibly) preferable construct (IMHO of course!) would be:
>
>
>   class Vector3D {
>        const double magnitude; // not a static member
>   public:
>        Vector3D(double x, double y, double z)
>           : magnitude( sqrt( x * x + y * y + z * z ) )
>         {
>         }
>   };

Of course it is preferable! Why assign when you can initialize?

The post that started the discussion involved using 'new' to initialize
a pointer, and not knowing whether the initialization had taken place
due to the possibility of an earlier exception. In that case you either
delete an uninitialized pointer, or have a memory leak.

If you initialize the pointer to zero and assign to the pointer in the
body of the ctor, you can then detect whether the assignment took place
and can do the proper cleanup.

---
Steve Clamage, stephen.clamage@eng.sun.com







Author: "Robert C. Martin" <rmartin@oma.com>
Date: 1995/05/19
Raw View
bartley@pact.srf.ac.uk (Mike Bartley) wrote:
>I am interested in what people think this code should do:
>
>void main()
>{
>  const int j = 0;
>  const int *pic = &j;
>  int *pi;
>
>  pi = (int *)pic;
>  *pi = 1;
>}
>
>I have tried it on Borland C++ (3.1) and g++. Both compiled.
>In Borland the last line had NO effect.
>In g++ the last line did change j.
>

It does not surprize me that the two compilers create different results.
It used to be that the compilation system was free to put const
primitive types into the code segment, so that they could be ROMMABLE.

I am not sure, but I think the standard has changed this now, and that
the above code *should* change j.



Robert Martin       | Design Consulting   | Training courses offered:
Object Mentor Assoc.| rmartin@rcmcon.com  |   Object Oriented Analysis
2080 Cranbrook Rd.  | Tel: (708) 918-1004 |   Object Oriented Design
Green Oaks IL 60048 | Fax: (708) 918-1023 |   C++







Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/05/19
Raw View
In article lih@news.wwa.com, "Robert C. Martin" <rmartin@oma.com> writes:
>bartley@pact.srf.ac.uk (Mike Bartley) wrote:
>>I am interested in what people think this code should do:
>>
>>void main()
>>{
>>  const int j = 0;
>>  const int *pic = &j;
>>  int *pi;
>>
>>  pi = (int *)pic;
>>  *pi = 1;
>>}
>>
>>I have tried it on Borland C++ (3.1) and g++. Both compiled.
>>In Borland the last line had NO effect.
>>In g++ the last line did change j.
>>
>
>It does not surprize me that the two compilers create different results.
>It used to be that the compilation system was free to put const
>primitive types into the code segment, so that they could be ROMMABLE.

This is still the case.

>I am not sure, but I think the standard has changed this now, and that
>the above code *should* change j.

No.