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.