Topic: Class representation in memory
Author: Jonathan de Boyne Pollard <J.deBoynePollard@tesco.net>
Date: 2000/06/13 Raw View
AA> What part of the standard allows or disallows this?
SC> You are allowed to write:
SC> A* p = (A*)malloc(sizeof A);
SC> new (p) A;
SC> That imposes a requirement that the storage of A be contiguous.
JdeBP> That is, at best, a circular argument. It certainly doesn't
JdeBP> answer the question asked. You are concluding that the
JdeBP> Standard imposes a requirement because one is allowed to write
JdeBP> a certain piece of code. Yet the premise would only be true
JdeBP> in the first place if the conclusion were already true. One
JdeBP> would only be allowed to write that code if the Standard
JdeBP> imposed the requirement.
HR> But the code above is perfectly legal, given 5.3.4/10 and
HR> 5.3.4/14. There is nothing circular about this argument.
There is nothing circular about *your* argument; but your answer isn't the
same as the one given (above) by Steve.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jonathan de Boyne Pollard <J.deBoynePollard@tesco.net>
Date: 2000/05/26 Raw View
JH> The implicitly-generated ctor is:
JH> Derived::Derived() : __base(new Base) {}
JH>
JH> The code generated for a new-expression does not change. You write:
JH> Base * b= new Derived;
JH>
JH> the compiler generates [pseudo-code, of course]:
JH> Base * tmp=operator new(sizeof Derived);
JH> tmp->Derived(); // see implementation just above
JH> Base *b=tmp;
JH>
JH> Hideously inefficient? Sure is. Conforming? As far as I can
JH> tell.
Consider the case where the first call to operator new succeeds but the second
(the implementation-generated one in the constructor) throws an exception.
Consider the case where what you actually wrote was instead:
Base * b= new(nothrow) Derived ;
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jonathan de Boyne Pollard <J.deBoynePollard@tesco.net>
Date: 2000/05/27 Raw View
AA> What part of the standard allows or disallows this?
SC> You are allowed to write:
SC> A* p = (A*)malloc(sizeof A);
SC> new (p) A;
SC> That imposes a requirement that the storage of A be contiguous.
That is, at best, a circular argument. It certainly doesn't answer the
question asked. You are concluding that the Standard imposes a requirement
because one is allowed to write a certain piece of code. Yet the premise
would only be true in the first place if the conclusion were already true.
One would only be allowed to write that code if the Standard imposed the
requirement.
I suspect that the issue here is one of those things that "everybody knows"
but that, when it comes down to it, is in fact quite hard to prove to be the
case from the actual text of the Standard. The wording that (quite rightly)
gives leeway to implementations on the placement of members with different
access specifiers, padding, virtual inheritance, no-member classes, and so
forth fails to clearly state that the storage for a most derived object is a
superset of the storage for all of its members and base sub-objects.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jonathan de Boyne Pollard <J.deBoynePollard@tesco.net>
Date: 2000/05/27 Raw View
AA> Yes, but doesn't the Standard guarantee there's only one call to
AA> operator new issued?
JH> I haven't seen that guarantee (doesn't mean it's not there, I
JH> probably missed it). 5.3.4/8 implies a single call, but does
JH> not explicitly prohibit multiple calls. Is the general rule
JH> "if it's not explicitly prohibited, it's allowed", or is it
JH> "if it's not explicitly allowed, it's prohibited"?
It is neither. The general rule, inasmuch as there is one, is "If it is not
explicit, it is undefined.".
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 2000/05/27 Raw View
Jonathan de Boyne Pollard <J.deBoynePollard@tesco.net> writes:
> AA> What part of the standard allows or disallows this?
> SC> You are allowed to write:
> SC> A* p = (A*)malloc(sizeof A);
> SC> new (p) A;
> SC> That imposes a requirement that the storage of A be contiguous.
>
> That is, at best, a circular argument. It certainly doesn't answer the
> question asked. You are concluding that the Standard imposes a requirement
> because one is allowed to write a certain piece of code. Yet the premise
> would only be true in the first place if the conclusion were already true.
> One would only be allowed to write that code if the Standard imposed the
> requirement.
But the code above is perfectly legal, given 5.3.4/10 and 5.3.4/14.
There is nothing circular about this argument.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: michael schilling <michael.schilling@Sun.COM>
Date: 2000/05/24 Raw View
Hyman Rosen wrote:
>
> fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
> > Certainly 1.8/5 does allow that. But I think the main intent
> > behind that wording is to allow discontinguous storage of the
> > object itself, which is needed for some base class sub-objects
> > in class hierarchies that make use of virtual inheritence.
> >
> > struct A {};
> > struct B : virtual A {};
> > struct C : virtual A {};
> > struct D : virtual A {};
> > struct E : A, B, C, D {} e;
> >
> > Apart from bizzare architectures (e.g. 2-D memory ;-), it is not
> > possible for the B, C, and D sub-objects of e to all be contiguous.
>
> This is irrelevant, because 1.8/5 is talking about most-derived objects.
> The most-derived object e does indeed occupy contiguous storage on all
> implementations that I know of (apart from the virtual table, of course).
>
And apart from any static members, of course. In a sense, the virtual
table *is* a static member (shared by all instances of the same class.)
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "John Hickin" <hickin@nortelnetworks.com>
Date: 2000/05/24 Raw View
Fergus Henderson wrote:
>
>
> No. There are good reasons why some implementations might do that.
> In particular, (a) it may be useful for reducing recompilation
> time, or (b) it may be useful for compatibility with the object
> layout of some other system (probably one that can exploit (a)
> more easily than C++ ;-).
>
(a) is definitely possible to achieve with a contiguous layout provided
that one introduces ancillary member offset tables and enforces that
object pointers contain two raw pointers (one to the top of the object
and one to an offset table). This approach may be found in a discussion
of object layout that appears in the Annotated C++ Reference Manual by
Ellis and Stroustrup. Achieving (b), OTOH, seems to me to require a
scatter allocator which would seem to disallow offset tables (presuming
them to be shared by al instances of a class).
Is it possible that an implementation might use placement new under the
hood provided that no (presumably incompatible) user-defined allocators
were present (addition of such a user allocator would require a complete
recompilation and a switch to a contiguous object representation).
The use of a scattered object representation has potential advantages
when it comes to exceptions. The representation seems essentially to be
that used in Java, the exception handling specification of which I like
better than that of C++. One can envision implementations where
destructors might throw exceptions without worry.
Regards, John.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "John Hickin" <hickin@nortelnetworks.com>
Date: 2000/05/10 Raw View
Andrei Alexandrescu wrote:
>
>
> 1. sizeof(obj) is greater than or equal to the sum of all its direct
> members.
>
>From the Annotated C++ Reference Manual, page 57:
struct r { s& r1; s& r2; };
noting that sizeof(s&) == sizeof(s).
Regards, John.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 2000/05/10 Raw View
Jim Hyslop <jim.hyslop@leitch.com> writes:
> I did not see anything that required the memory for Base to be
> contiguous with the memory for Derived. In other words, a compiler
> could calculate sizeof(Derived) as:
> sizeof(Base *)+sizeof(int)
> and allocate 30 bytes for Base in a separate block of memory.
But from where is it going to get that memory?
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 2000/05/10 Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
> Certainly 1.8/5 does allow that. But I think the main intent
> behind that wording is to allow discontinguous storage of the
> object itself, which is needed for some base class sub-objects
> in class hierarchies that make use of virtual inheritence.
>
> struct A {};
> struct B : virtual A {};
> struct C : virtual A {};
> struct D : virtual A {};
> struct E : A, B, C, D {} e;
>
> Apart from bizzare architectures (e.g. 2-D memory ;-), it is not
> possible for the B, C, and D sub-objects of e to all be contiguous.
This is irrelevant, because 1.8/5 is talking about most-derived objects.
The most-derived object e does indeed occupy contiguous storage on all
implementations that I know of (apart from the virtual table, of course).
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Robert Klemme <robert.klemme@myview.de>
Date: 2000/05/10 Raw View
maxim schrieb:
>=20
> what if Andrei wants to write a C++ compliler or interpretor?
then he would be totally free to fix this for his implementation. :-)
robert
--=20
Robert Klemme
Software Engineer
-------------------------------------------------------------
myview technologies GmbH & Co. KG
Riemekestra=DFe 160 ~ D-33106 Paderborn ~ Germany
E-Mail: mailto:robert.klemme@myview.de
Telefon: +49/5251/69090-321 ~ Fax: +49/5251/69090-399
-------------------------------------------------------------
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: scorp@btinternet.com (Dave Harris)
Date: 2000/05/10 Raw View
jim.hyslop@leitch.com (Jim Hyslop) wrote:
> An implementation could, as far as I can see, give Derived a size of 30
> + sizeof(Base *). This would, of course, be horrendously inefficient
> since dynamic allocation will require a call to new for each base class
> in the object.
What happens if there is a user-defined operator new()? Presumably it
would be called twice, with 2 different argument sizes. This would be
visible to the user.
At one time I strongly felt that this freedom ought to be available to the
compiler. For example, it allows sizeof(Derived) to be independent of
sizeof(Base). Variations would include using a similar approach for
private data, as a kind of automatic "pImpl/Cheshire cat" idiom. The idea
would be to reduce dependencies. Adding a private variable or virtual
function to Base would not cause members in Derived to change offset.
However, in practice "private" is leaky enough that we have to
re-type-check users of Derived anyway, and if we are doing that we might
as well recompile them, so the benefit of the indirection is largely lost.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 2000/05/11 Raw View
Hyman Rosen <hymie@prolifics.com> writes:
>fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
>> Certainly 1.8/5 does allow that. But I think the main intent
>> behind that wording is to allow discontinguous storage of the
>> object itself, which is needed for some base class sub-objects
>> in class hierarchies that make use of virtual inheritence.
>>
>> struct A {};
>> struct B : virtual A {};
>> struct C : virtual A {};
>> struct D : virtual A {};
>> struct E : A, B, C, D {} e;
>>
>> Apart from bizzare architectures (e.g. 2-D memory ;-), it is not
>> possible for the B, C, and D sub-objects of e to all be contiguous.
>
>This is irrelevant, because 1.8/5 is talking about most-derived objects.
>The most-derived object e does indeed occupy contiguous storage on all
>implementations that I know of (apart from the virtual table, of course).
1.8/5 has three sentences:
| -5- Unless it is a bit-field (class.bit), a most derived object shall
| have a non-zero size and shall occupy one or more bytes of storage.
| Base class sub-objects may have zero size. An object of POD
| type (basic.types) shall occupy contiguous bytes of storage.
The first sentence is talking about "most derived" objects.
The second sentence is talking about "base class sub-objects".
But the third sentence, the one that has the wording about
contiguousness, refers just to objects of "POD type".
--
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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 2000/05/11 Raw View
In article <t7ya5j345m.fsf@calumny.jyacc.com>,
Hyman Rosen <hymie@prolifics.com> wrote:
> Jim Hyslop <jim.hyslop@leitch.com> writes:
> > I did not see anything that required the memory for Base to be
> > contiguous with the memory for Derived. In other words, a compiler
> > could calculate sizeof(Derived) as:
> > sizeof(Base *)+sizeof(int)
> > and allocate 30 bytes for Base in a separate block of memory.
>
> But from where is it going to get that memory?
By calling operator new.
Let me put it this way - as far as I can tell, a compiler can implement
a derived class as if you wrote:
class Derived
{
public:
Base * __base;
};
Let me emphasize that this is only in terms of *storage*, and what
happens under the hood. You write:
class Base
{
char array[30];
public:
int aFunction();
virtual ~Base();
};
class Derived : public Base
{
int i;
public:
int anotherFunction() { return aFunction(); }
};
int main()
{
Derived d;
d.aFunction();
}
The compiler generates its machine code and storage requirements *as*if*
you wrote (generating machine code is, of course, the last step of the
compile process, so access privileges, etc. have already been checked):
// Same Base as above
class Derived
{
public:
Base * __base;
public:
int anotherFunction() { return __base->aFunction(); }
};
int main()
{
Derived d;
d.__base->aFunction();
}
The implicitly-generated ctor is:
Derived::Derived()
:
__base(new Base)
{
}
The code generated for a new-expression does not change. You write:
Base * b= new Derived;
the compiler generates [pseudo-code, of course]:
Base * tmp=operator new(sizeof Derived);
tmp->Derived(); // see implementation just above
Base *b=tmp;
Suppose we're on a platform with 4-byte ints, and 4-byte pointers, using
a vtable implementation. Sizeof(Derived) will be:
sizeof(vptr) + sizeof(Base *) + sizeof(int)
Hideously inefficient? Sure is. Conforming? As far as I can tell.
--
Jim
I ignore all email from recruitment agencies. Except that
I reserve the right to send rude, nasty replies to recruiters.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 2000/05/11 Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
> 1.8/5 has three sentences:
> | -5- Unless it is a bit-field (class.bit), a most derived object shall
> | have a non-zero size and shall occupy one or more bytes of storage.
> | Base class sub-objects may have zero size. An object of POD
> | type (basic.types) shall occupy contiguous bytes of storage.
> The first sentence is talking about "most derived" objects.
> The second sentence is talking about "base class sub-objects".
> But the third sentence, the one that has the wording about
> contiguousness, refers just to objects of "POD type".
My point is that the last sentence could equally well be
A most derived object shall occupy contiguous bytes of storage.
except that the Standard wants to allow for a separately stored dispatch
table. I know of no implementation which violates this version of the
sentence, and I don't know how you could create such an implementation
without running afoul of placement new.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 2000/05/11 Raw View
> > But from where is it going to get that memory?
> By calling operator new.
Yes, but doesn't the Standard guarantee there's only one call to
operator new issued?
This is not a lot of relief, though. The compiler could allocate the
base object(s) from another heap.
Andrei
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Barry Margolin <barmar@genuity.net>
Date: 2000/05/11 Raw View
In article <39182AEC.B5B7AB3B@myview.de>,
Robert Klemme <robert.klemme@myview.de> wrote:
>
>
>maxim schrieb:
>>
>> what if Andrei wants to write a C++ compliler or interpretor?
>
>then he would be totally free to fix this for his implementation. :-)
Maxim was replying to the question of why the OP needs to know this. The
point of his reply was that an implementor needs to know what requirements
and restrictions the standard mandates on him regarding object layout. In
that context, the original question makes perfect sense.
However, the sense I got from the original posting was that this was not
why he wanted to know.
--
Barry Margolin, barmar@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 2000/05/12 Raw View
In article <memo.20000509184704.56055G@btinternet.com>,
brangdon@cix.co.uk wrote:
> jim.hyslop@leitch.com (Jim Hyslop) wrote:
> > An implementation could, as far as I can see, give Derived a size of
> > 30
> > + sizeof(Base *). This would, of course, be horrendously
> > inefficient
> > since dynamic allocation will require a call to new for each base
> > class
> > in the object.
[snip]
> At one time I strongly felt that this freedom ought to be available to
> the compiler.
So, would it be a fair statement to say that, although there is no
requirement for a compiler to use a contiguous block of memory to hold a
derived class and all its base class non-static data members, it is
impractical for a compiler to place a derived class in a memory segment
that is not contiguous with its base class members?
That is, for any object of most-derived-type O, with a sub-object M, the
following condition will be true:
((char *)&O) <= ((char *)(&O.M)) &&
((char *)(&O.M)) < ((char *)(&O + sizeof(O)))
[where "&O.M" could also be a cast to a base class of O, i.e.
static_cast<Base *>(&O)]
This condition is not required by the Standard, but it is impractical
*not* to implement it in this way.
--
Jim
I ignore all email from recruitment agencies. Except that
I reserve the right to send rude, nasty replies to recruiters.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 2000/05/12 Raw View
In article <t74s862fpb.fsf@calumny.jyacc.com>,
Hyman Rosen <hymie@prolifics.com> wrote:
[snip]
> My point is that the last sentence could equally well be
>
> A most derived object shall occupy contiguous bytes of storage.
>
> except that the Standard wants to allow for a separately stored
> dispatch table.
The dispatch table is not a member of the class, a *pointer* to the
table is a member, just as if you wrote:
struct someInfo
{
void *table[100];
};
namespace
{
someInfo si;
}
class T
{
someInfo *infoPtr;
protected:
int i;
public:
T() : infoPtr(si) {}
};
sizeof(T) will be sizeof(someInfo *) [+ implementation-specific
alignment/padding bytes]
The object T will occupy a contiguous memory block (in practise at
least, even if it's not required in the Standard).
--
Jim
I ignore all email from recruitment agencies. Except that
I reserve the right to send rude, nasty replies to recruiters.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 2000/05/12 Raw View
Jim Hyslop <jim.hyslop@leitch.com> writes:
> The implicitly-generated ctor is:
> Derived::Derived()
> :
> __base(new Base)
> {
> }
This is the problem - the compiler can't just go off and willy-nilly call
new in the middle of the construction. Or at least, I don't think it can.
How would this interact with placement new?
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 2000/05/12 Raw View
In article <8feege$67$1@nnrp1.deja.com>, Jim Hyslop
<jim.hyslop@leitch.com> writes
>The dispatch table is not a member of the class, a *pointer* to the
>table is a member, just as if you wrote:
As the Standard does not mandate how virtual dispatch should be made to
work I do not think either of those statements is correct. Both the
pointer and the table are part of the implementation details which can
be done as inefficiently and bizarrely as the implementor desires as
long as the mechanism achieves the required objective,
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 2000/05/12 Raw View
In article <shjpr8opd5817@news.supernews.com>,
"Andrei Alexandrescu" <andrewalex@hotmail.com> wrote:
> > > But from where is it going to get that memory?
> > By calling operator new.
>
> Yes, but doesn't the Standard guarantee there's only one call to
> operator new issued?
I haven't seen that guarantee (doesn't mean it's not there, I probably
missed it). 5.3.4/8 implies a single call, but does not explicitly
prohibit multiple calls. Is the general rule "if it's not explicitly
prohibited, it's allowed", or is it "if it's not explicitly allowed,
it's prohibited"?
Even so, if the compiler defines the size of a derived class in the
manner I posted earlier, it would still be a single allocation to obtain
storage for the Derived class. Allocation for the Base class would be
part of the initialization sequence of Derived. It would be analogous
to containment by pointer, i.e.:
class T {};
class U
{
T *t;
public:
U() : t(new T) {}
};
There is one restriction on my, um, "technique" - 3.7.3/4 means that a
derived object that is thrown cannot call a global allocation function,
e.g.:
throw Derived;
This would complicate (but not necessarily invalidate) the mechanism
I've shown - the pointer does not *have* to be allocated, but could be
reserved some other way (perhaps by reserving a segment of memory for
exception objects). This would now require a flag for each object
indicating whether the Base portion was dynamically allocated.
Again, it's hideously complex, and probably so error-prone and
inefficient that nobody in their right mind would do it - which is
likely why the Committee either did not consider the possibility, or
decided not to bother mentioning it in the Standard :-)
[Warning: change of direction]
Ah, I think I have a line of reasoning that may blow away my
hypothetical compiler.
Clause 10, paragraph 2 (I abbreviated the example slightly):
"The base-specifier-list specifies the type of the base class subobjects
contained in an object of the derived class type. [Example:
class Base { /*...*/};
class Derived : public Base { /*...*/ };
class Derived2 : public Derived { /*...*/ };
Here, an object of Derived2 will have a sub-object of class Derived
which in turn will have a sub-object of class Base. ]"
The key words are "contained" and "will have a sub-object..." - Derived
must contain a Base object. Not a pointer to a Base, not a reference to
a Base, a Base object.
Therefore, sizeof(Derived) must be at least as large as sizeof(Base) +
sizeof(all members of Derived) [plus padding, etc., and where sizeof()
can be 0 if the object has no members].
--
Jim
I ignore all email from recruitment agencies. Except that
I reserve the right to send rude, nasty replies to recruiters.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 2000/05/12 Raw View
In article <shjpr8opd5817@news.supernews.com>, Andrei Alexandrescu
<andrewalex@hotmail.com> writes
>> > But from where is it going to get that memory?
>> By calling operator new.
>
>Yes, but doesn't the Standard guarantee there's only one call to
>operator new issued?
>
>This is not a lot of relief, though. The compiler could allocate the
>base object(s) from another heap.
Actually, I thought implementations were actually prohibited from using
operator new behind your back.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 2000/05/12 Raw View
Barry Margolin <barmar@genuity.net> wrote in message
news:INhS4.53$pj4.2131@burlma1-snr2...
> However, the sense I got from the original posting was that this was
not
> why he wanted to know.
I just want to make Scott Meyers' double dispatch engine work with
inheritance. I will post this as soon as I can.
Andrei
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 2000/05/13 Raw View
In article <t71z3a2exe.fsf@calumny.jyacc.com>,
Hyman Rosen <hymie@prolifics.com> wrote:
> Jim Hyslop <jim.hyslop@leitch.com> writes:
> > The implicitly-generated ctor is:
> > Derived::Derived()
> > :
> > __base(new Base)
> > {
> > }
>
> This is the problem - the compiler can't just go off and willy-nilly
> call
> new in the middle of the construction. Or at least, I don't think it
> can.
You're right, it can't if I read 3.7.3.1 correctly (I hadn't considered
that clause earlier).
> How would this interact with placement new?
Ick.
OK, I'm convinced my hypothetical compiler cannot work, and is not
conforming.
At this point, I don't see anything that would contradict Andrei's
requirement for an object to occupy contiguous memory.
--
Jim
I ignore all email from recruitment agencies. Except that
I reserve the right to send rude, nasty replies to recruiters.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 2000/05/13 Raw View
In article <+$JqT9A6osG5EwoK@robinton.demon.co.uk>,
Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
> In article <shjpr8opd5817@news.supernews.com>, Andrei Alexandrescu
> <andrewalex@hotmail.com> writes
> >> > But from where is it going to get that memory?
> >> By calling operator new.
> >
> >Yes, but doesn't the Standard guarantee there's only one call to
> >operator new issued?
> >
> >This is not a lot of relief, though. The compiler could allocate the
> >base object(s) from another heap.
>
> Actually, I thought implementations were actually prohibited from
> using
> operator new behind your back.
Yes, good point - 3.7.3.1/4 pretty much says that all calls to the
allocation function must be explicitly made. OK, that blows away my
hypothetical compiler (good!!).
--
Jim
I ignore all email from recruitment agencies. Except that
I reserve the right to send rude, nasty replies to recruiters.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Bill Wade" <bill.wade@stoner.com>
Date: 2000/05/13 Raw View
"Jim Hyslop" <jim.hyslop@leitch.com> wrote in message
> Ah, I think I have a line of reasoning that may blow away my
> hypothetical compiler.
>
> Clause 10, paragraph 2 (I abbreviated the example slightly):
>
> "The base-specifier-list specifies the type of the base class subobjects
> contained in an object of the derived class type [example deleted]"
>
> The key words are "contained" and "will have a sub-object..." - Derived
> must contain a Base object. Not a pointer to a Base, not a reference to
> a Base, a Base object.
It all depends on your definition of "contained." Note that a vector<T>, v,
which is not empty "contains" a T sub-object. However, in most
implementations the T sub-object does not live in [(char*)&v,
(char*)&v+sizeof v)
While I expect class objects to be contiguous, I'm not at all convinced the
standard makes that a requirement for non-POD. In particular some parts of
the standard seem to be written specifically to allow non-contiguous
objects.
3.8/7 seems to say that if a derived object is destroyed and then
reconstructed (with placement new), existing pointers to base-class
sub-objects are no longer valid. That is exactly the kind of implementation
freedom which seems to be specifically written to allow non-contiguous
derived objects.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 2000/05/17 Raw View
Jim Hyslop <jim.hyslop@leitch.com> writes:
>In article <memo.20000509184704.56055G@btinternet.com>,
> brangdon@cix.co.uk wrote:
>> jim.hyslop@leitch.com (Jim Hyslop) wrote:
>> > An implementation could, as far as I can see, give Derived a size of
>> > 30
>> > + sizeof(Base *). This would, of course, be horrendously
>> > inefficient
>> > since dynamic allocation will require a call to new for each base
>> > class
>> > in the object.
>[snip]
>> At one time I strongly felt that this freedom ought to be available to
>> the compiler.
>
>So, would it be a fair statement to say that, although there is no
>requirement for a compiler to use a contiguous block of memory to hold a
>derived class and all its base class non-static data members, it is
>impractical for a compiler to place a derived class in a memory segment
>that is not contiguous with its base class members?
No. There are good reasons why some implementations might do that.
In particular, (a) it may be useful for reducing recompilation
time, or (b) it may be useful for compatibility with the object
layout of some other system (probably one that can exploit (a)
more easily than C++ ;-).
--
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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 2000/05/17 Raw View
Hyman Rosen <hymie@prolifics.com> writes:
>Jim Hyslop <jim.hyslop@leitch.com> writes:
>> I did not see anything that required the memory for Base to be
>> contiguous with the memory for Derived. In other words, a compiler
>> could calculate sizeof(Derived) as:
>> sizeof(Base *)+sizeof(int)
>> and allocate 30 bytes for Base in a separate block of memory.
>
>But from where is it going to get that memory?
There are many places it could get the memory from.
For example, it could get it from malloc(), or mmap(), or brk(),
or some other OS system call.
--
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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Robert Klemme <robert.klemme@myview.de>
Date: 2000/05/09 Raw View
hi!
when reading your post this question arouse to me: why does he want to
know this? i did not find your motivation here. normally i would say,
that you should not bother how compilers do implement this.
Andrei Alexandrescu schrieb:
> My question is: what portable assumptions can I make about the size
> and the layout of A in memory?
again: why do you need to make these?
> In other words: is an object a comprehensive, inclusive storage for
> all of its bases and members? By reading the standard, I feel this is
> implied in a lot of places, but I didn't find a place where that's
> stated bluntly. Well, I need that blunt statement.
what, if there is no such statement? what, if the standards commitee
wanted to qualify this as an implementation detail? if i would be the
commitee i would not have stated how this should be done.
> Any help would be greatly appreciated.
sorry for beeing that unhelpful, but i have the feeling that - since you
did search the standard and found nothing - there is really nothing to
be found. and i think this is completely reasonable.
regards
robert
--=20
Robert Klemme
Software Engineer
-------------------------------------------------------------
myview technologies GmbH & Co. KG
Riemekestra=DFe 160 ~ D-33106 Paderborn ~ Germany
E-Mail: mailto:robert.klemme@myview.de
Telefon: +49/5251/69090-321 ~ Fax: +49/5251/69090-399
-------------------------------------------------------------
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 2000/05/09 Raw View
"Andrei Alexandrescu" <andrewalex@hotmail.com> writes:
> In other words: is an object a comprehensive, inclusive storage for
> all of its bases and members? By reading the standard, I feel this is
> implied in a lot of places, but I didn't find a place where that's
> stated bluntly. Well, I need that blunt statement.
1.8/5 says that an object of POD type shall occupy contiguous bytes of
storage, which clearly implies that the Standard makes no such
requirement on non-POD objects. The ability to access the bytes of an
object using memcpy is given only to POD objects as well.
Most implementations store virtual dispatch tables separately from
the objects which use them, which is presumably what 1.8/5 means to
allow.
The discussion of new expressions in 5.3.4 seems to make it clear that
the allocation function is called only once, and for non-arrays is
called with exactly sizeof the object to be created, so it seems
unlikely that it's possible for an implementation to store varying
parts of an object in non-contiguous storage.
This is probably enough to guarantee that the code you want to write
will be portable to all implementations.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jerry Coffin <jcoffin@taeus.com>
Date: 2000/05/09 Raw View
In article <sha6e9suqil23@news.supernews.com>, andrewalex@hotmail.com
says...
> I know this is pretty darn silly, but I really need help and I guess
> it's better to make a fool of myself, than shutting my mouth up and
> remaining shaded by the darkness of obscurantism.
>
> I formulated a similar question in clc++m, but unfortunately didn't
> get enough answers. I'll try to be more cunning here so as to attract
> more interest and therefore more answers. It all depends on how you
> ask the question :o).
>
> It's all very simple (cunning, huh?). I have a little class.
>
> class A : public Base
> {
> char sample[50];
> ...
> };
>
> My question is: what portable assumptions can I make about the size
> and the layout of A in memory?
That depends on the base class and what the "..." contains. At least
as far as I can see, having a base class, by itself, doesn't prevent
this from being a POD-class. If it IS a POD class, you can depend on
a few things. If it's not, (e.g. the base class or the "..."
includes a user-defined dtor) then you can't depend on much of
anything.
Looking through things, I spotted one thing I _think_ may be an error
(though I haven't looked through the core-language issue list to see
if it's already been noted). Section 1.8/5 says that "an object of
POD type (3.9) shall occupy contiguous bytes of storage." I believe
the intent of POD types is that they be be layout-compatible with C
types (e.g. a legal C struct definition compiled as C++ should retain
essentially the same layout). The members of a C struct, however,
are not required to be contiguous -- they're required to be allocated
in ascending order, but may have padding between them.
--
Later,
Jerry.
The universe is a figment of its own imagination.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 2000/05/09 Raw View
Robert Klemme <robert.klemme@myview.de> wrote in message
news:3916D770.B602EAA5@myview.de...
>when reading your post this question arouse to me: why does he want
to
know this? i did not find your motivation here. normally i would
say,
that you should not bother how compilers do implement this.<
I happen to bother because that would help me make Scott Meyers'
double dispatch engine work with inheritance.
>what, if there is no such statement? what, if the standards commitee
wanted to qualify this as an implementation detail? if i would be the
commitee i would not have stated how this should be done.<
Watch for what others will say. We might have a surprise.
Andrei
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 2000/05/09 Raw View
In article <sha6e9suqil23@news.supernews.com>,
"Andrei Alexandrescu" <andrewalex@hotmail.com> wrote:
> I know this is pretty darn silly, but I really need help and I guess
> it's better to make a fool of myself, than shutting my mouth up and
> remaining shaded by the darkness of obscurantism.
>
> I formulated a similar question in clc++m, but unfortunately didn't
> get enough answers. I'll try to be more cunning here so as to attract
> more interest and therefore more answers. It all depends on how you
> ask the question :o).
>
> It's all very simple (cunning, huh?). I have a little class.
>
> class A : public Base
> {
> char sample[50];
> ...
> };
>
> My question is: what portable assumptions can I make about the size
> and the layout of A in memory?
>
> I want to make it clear that I'm not lazy. I did my homework - I
> looked in the standard, but somehow I always have trouble verifying
> integrating questions like that. I found some implications in 3.9.2/1,
> Compound Types. There the doc says classes contain "a sequence of
> objects of various types". But that's not enough. 9.2/12 makes
> interesting statements, but again it's all not crystal-clear.
>
> Is there a guarantee that says A aggregates A::sample directly? For
> instance, a C++ interpreter could store a pointer to A::sample inside
> A, instead of storing the fifty characters. In this case, sizeof(A) is
> not necessarily greater than sizeof(A().sample). Would that be a
> conforming C++ implementation? What part of the standard allows or
> disallows this?
A pointer-to-char is not the same as an array of char. 8.3.4 states "an
object of array type contains a contiguously allocated non-empty set of
N sub-objects of type T." So I'd say if a compiler substituted a
pointer for an array, it is not conforming. Therefore, sizeof(A) is
required to be a minimum of 50.
> I want to make sure the whether the following things are true or not.
> Any quote to the standard would be of big help.
>
> 1. sizeof(obj) is greater than or equal to the sum of all its direct
> members.
> 2. the address of each member of obj casted to const char* is in
> between the address of obj and the address of obj plus sizeof(obj),
> casted to char.
In other words, something like this:
struct T
{
int x, y, z;
};
void f()
{
T t;
assert((char *)&t.x >= (char *)&t);
assert((char *)&t.x < (char *)&t+sizeof(t));
}
and so on, right?
The last part of 9.2/12 implies this, but does not explicitly state it.
Ah, here's an angle - the allocation function (3.7.3.1). An allocation
function returns a pointer to a block of storage (drat, it's not
specified as a contiguous block!!) that is at least as large as the
requested size. For a single object, the size that the new expression
passes to operator new must be equal to the object's size (5.3.4/10).
> Supplemental question: does this apply to base
> classes? Supplementalmental (sic) question: does this apply to virtual
> base classes?
Good question. I didn't see anything in the Standard which would
preclude an implementation from using a pointer to a base class instead
of including the base class directly, e.g.:
class Base
{
char c[20];
};
class Derived : public Base
{
char d[30];
};
An implementation could, as far as I can see, give Derived a size of 30
+ sizeof(Base *). This would, of course, be horrendously inefficient
since dynamic allocation will require a call to new for each base class
in the object.
> In other words: is an object a comprehensive, inclusive storage for
> all of its bases and members? By reading the standard, I feel this is
> implied in a lot of places, but I didn't find a place where that's
> stated bluntly. Well, I need that blunt statement.
Oh, here we go: 1.8/5: "Unless it is a bitfield, a most derived object
shall have a non-zero size and shall occupy one or more bytes of
storage.... An object of POD type (3.9) shall occupy contiguous bytes
of storage."
Since the clause explicitly requires a POD type to have contiguous
storage but does not put such a requirement on non-PODs, I infer that
non-PODs are not required to have contiguous storage.
OK, that's my kick at the can - anyone else want to have a go?
--
Jim
I ignore all email from recruitment agencies. Except that
I reserve the right to send rude, nasty replies to recruiters.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "maxim" <maxk@NOSPAMtouro.edu>
Date: 2000/05/09 Raw View
Robert Klemme <robert.klemme@myview.de> wrote in message
news:3916D770.B602EAA5@myview.de...
>hi!
>when reading your post this question arouse to me: why does he want to
>know this? i did not find your motivation here. normally i would say,
>that you should not bother how compilers do implement this.
>again: why do you need to make these?
what if Andrei wants to write a C++ compliler or interpretor?
max.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 2000/05/09 Raw View
In article <sha6e9suqil23@news.supernews.com>, Andrei Alexandrescu
<andrewalex@hotmail.com> writes
>1. sizeof(obj) is greater than or equal to the sum of all its direct
>members.
But there is no such guarantee. Apart from anything else all complete
objects must have a size greater than zero but a sub-object may have a
size of zero.
You are not allowed to have two sub-objects of the same type with the
same address (even if they are zero sized) but I believe that you are
allowed to have as many sub-objects as you like with the same address if
they are of different types. Remember that you are only allowed to
compare addresses of the same type.
Yes, it can get quite complicated but fundamentally derived objects can
use the alignment space from a base for the derived data.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 2000/05/09 Raw View
Jerry Coffin <jcoffin@taeus.com> wrote in message
news:MPG.1380d4af1604e6eb989870@news.mindspring.com...
> That depends on the base class and what the "..." contains. At
least
> as far as I can see, having a base class, by itself, doesn't prevent
> this from being a POD-class. If it IS a POD class, you can depend
on
> a few things. If it's not, (e.g. the base class or the "..."
> includes a user-defined dtor) then you can't depend on much of
> anything.
The class is not a POD because it has private data.
Andrei
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Steven King <sxking@uswest.net>
Date: 2000/05/09 Raw View
>
> 1. sizeof(obj) is greater than or equal to the sum of all its direct
> members.
>
> 2. the address of each member of obj casted to const char* is in
> between the address of obj and the address of obj plus sizeof(obj),
> casted to char. Supplemental question: does this apply to base
> classes? Supplementalmental (sic) question: does this apply to virtual
> base classes?
>
> In other words: is an object a comprehensive, inclusive storage for
> all of its bases and members? By reading the standard, I feel this is
> implied in a lot of places, but I didn't find a place where that's
> stated bluntly. Well, I need that blunt statement.
How about 9.2/12?
"Nonstatic data members of a (non-union) class declared without an
intervening access-specifier are allocated
so that later members have higher addresses within a class object. The order
of allocation of nonstatic
data members separated by an access-specifier is unspecified (11.1)."
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 2000/05/09 Raw View
In article <t7wvl4aikm.fsf@calumny.jyacc.com>,
Hyman Rosen <hymie@prolifics.com> wrote:
> "Andrei Alexandrescu" <andrewalex@hotmail.com> writes:
> > In other words: is an object a comprehensive, inclusive storage for
> > all of its bases and members? By reading the standard, I feel this
is
> > implied in a lot of places, but I didn't find a place where that's
> > stated bluntly. Well, I need that blunt statement.
[snip]
> The discussion of new expressions in 5.3.4 seems to make it clear that
> the allocation function is called only once, and for non-arrays is
> called with exactly sizeof the object to be created, so it seems
> unlikely that it's possible for an implementation to store varying
> parts of an object in non-contiguous storage.
OK, but what is the size of the object in question? For example, as I
posted elsewhere in this thread, if you have:
class Base
{
char a[30];
};
class Derived : public Base
{
int x;
};
I did not see anything that required the memory for Base to be
contiguous with the memory for Derived. In other words, a compiler
could calculate sizeof(Derived) as:
sizeof(Base *)+sizeof(int)
and allocate 30 bytes for Base in a separate block of memory.
Granted, it's likely that the *intent* of these clauses is to allocate a
single, contiguous block of memory that contains the data members of
Base, the data members of Derived, and any other information (such as
vptrs) to implement virtual dispatch, and the vagueness about ordering
is there to give the compiler writers leeway as to exactly how they lay
out the block. But, like Andrei, I haven't found anything to *require*
such behaviour.
--
Jim
I ignore all email from recruitment agencies. Except that
I reserve the right to send rude, nasty replies to recruiters.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Steve Clamage <stephen.clamage@sun.com>
Date: 2000/05/10 Raw View
Andrei Alexandrescu wrote:
>
> It's all very simple (cunning, huh?). I have a little class.
>
> class A : public Base
> {
> char sample[50];
> ...
> };
>
> My question is: what portable assumptions can I make about the size
> and the layout of A in memory?
You can assume that the size of A will be at least 50 bytes, and
will be aligned according to the requirements of other types
that are members of A and B. A char array does not ordinarily
affect the alignment of a class, although a platform might choose
to align objects based on their size as well as their type.
>
> I want to make it clear that I'm not lazy. I did my homework - I
> looked in the standard, but somehow I always have trouble verifying
> integrating questions like that.
The size and alignment of objects is almost entirely implementation
dependent. The standard makes few requirements.
One requirement is that the addresses of non-bitfield member data
between access modifiers have increasing addresses in declaration
order.
> Is there a guarantee that says A aggregates A::sample directly? For
> instance, a C++ interpreter could store a pointer to A::sample inside
> A, instead of storing the fifty characters. In this case, sizeof(A) is
> not necessarily greater than sizeof(A().sample). Would that be a
> conforming C++ implementation? What part of the standard allows or
> disallows this?
You are allowed to write:
A* p = (A*)malloc(sizeof A);
new (p) A;
That imposes a requirement that the storage of A be contiguous.
At least, I think it does.
> 1. sizeof(obj) is greater than or equal to the sum of all its direct
> members.
In some cases, objects without data can have the same address when
they are part of a class. As independent objects, the sizeof
operator cannot return 0, however. Example:
class B { };
class C { };
class A : public B, public C { };
It is possible for sizeof(A), sizeof(B), and sizeof(C) all to be 1.
>
> 2. the address of each member of obj casted to const char* is in
> between the address of obj and the address of obj plus sizeof(obj),
> casted to char. Supplemental question: does this apply to base
> classes? Supplementalmental (sic) question: does this apply to virtual
> base classes?
The storage for a class T object must be contiguous, but the compiler
is allowed to play games with positive and negative offsets from
the value returned by &obj. For example, one implementation put
the vtable pointer at a negative offset from &obj. (The compiler
must adjust conversions between T* and void* in that case.)
--
Steve Clamage, stephen.clamage@sun.com
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Peter Morse" <peterm@sedona.net>
Date: 2000/05/10 Raw View
> Section 1.8/5 says that "an object of
> POD type (3.9) shall occupy contiguous bytes of storage." I believe
> the intent of POD types is that they be be layout-compatible with C
> types (e.g. a legal C struct definition compiled as C++ should retain
> essentially the same layout). The members of a C struct, however,
> are not required to be contiguous -- they're required to be allocated
> in ascending order, but may have padding between them.
"shall occupy contiguous bytes of storage" does not say or imply it does not
contain pad bytes
The only thing it says is that a POD shall occupy sizeof(POD) contiguous
bytes
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Dag Henriksson" <dag.henriksson@quidsoft.se>
Date: 2000/05/10 Raw View
"Jerry Coffin" <jcoffin@taeus.com> wrote in message
news:MPG.1380d4af1604e6eb989870@news.mindspring.com...
> That depends on the base class and what the "..." contains. At least
> as far as I can see, having a base class, by itself, doesn't prevent
> this from being a POD-class
A class having a base class is not a POD.
8.5.1p1 "An aggregate is an array or a class with ... no base classes".
9p4 "A POD struct is an aggregate class..."
-- Dag Henriksson
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jthill@telus.net (Jim Hill)
Date: 2000/05/10 Raw View
Jerry Coffin <jcoffin@taeus.com> wrote:
> At least as far as I can see, having a base class, by itself, doesn't
> prevent this from being a POD-class.
It does. POD-classes are aggregates, which may not have base classes.
> Section 1.8/5 says that "an object of POD type (3.9) shall occupy
> contiguous bytes of storage." [...]
It's true that the members need not be contiguous, but the object
needn't contain only members: in both C and C++, it can also contain
padding. The language you cite doesn't say "the members of an object of
POD type shall occupy contiguous bytes of storage".
Jim
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 2000/05/10 Raw View
Hyman Rosen <hymie@prolifics.com> writes:
>"Andrei Alexandrescu" <andrewalex@hotmail.com> writes:
>> In other words: is an object a comprehensive, inclusive storage for
>> all of its bases and members? By reading the standard, I feel this is
>> implied in a lot of places, but I didn't find a place where that's
>> stated bluntly. Well, I need that blunt statement.
>
>1.8/5 says that an object of POD type shall occupy contiguous bytes of
>storage, which clearly implies that the Standard makes no such
>requirement on non-POD objects. The ability to access the bytes of an
>object using memcpy is given only to POD objects as well.
>
>Most implementations store virtual dispatch tables separately from
>the objects which use them, which is presumably what 1.8/5 means to
>allow.
Certainly 1.8/5 does allow that. But I think the main intent
behind that wording is to allow discontinguous storage of the
object itself, which is needed for some base class sub-objects
in class hierarchies that make use of virtual inheritence.
E.g.
struct A {};
struct B : virtual A {};
struct C : virtual A {};
struct D : virtual A {};
struct E : A, B, C, D {} e;
Apart from bizzare architectures (e.g. 2-D memory ;-), it is not
possible for the B, C, and D sub-objects of e to all be contiguous.
--
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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/05/10 Raw View
Jim Hyslop wrote:
>
> In article <sha6e9suqil23@news.supernews.com>,
> "Andrei Alexandrescu" <andrewalex@hotmail.com> wrote:
> > I know this is pretty darn silly, but I really need help and I guess
> > it's better to make a fool of myself, than shutting my mouth up and
> > remaining shaded by the darkness of obscurantism.
> >
> > I formulated a similar question in clc++m, but unfortunately didn't
> > get enough answers. I'll try to be more cunning here so as to attract
> > more interest and therefore more answers. It all depends on how you
> > ask the question :o).
> >
> > It's all very simple (cunning, huh?). I have a little class.
> >
> > class A : public Base
> > {
> > char sample[50];
> > ...
> > };
> >
> > My question is: what portable assumptions can I make about the size
> > and the layout of A in memory?
> >
> > I want to make it clear that I'm not lazy. I did my homework - I
> > looked in the standard, but somehow I always have trouble verifying
> > integrating questions like that. I found some implications in 3.9.2/1,
> > Compound Types. There the doc says classes contain "a sequence of
> > objects of various types". But that's not enough. 9.2/12 makes
> > interesting statements, but again it's all not crystal-clear.
> >
> > Is there a guarantee that says A aggregates A::sample directly? For
> > instance, a C++ interpreter could store a pointer to A::sample inside
> > A, instead of storing the fifty characters. In this case, sizeof(A) is
> > not necessarily greater than sizeof(A().sample). Would that be a
> > conforming C++ implementation? What part of the standard allows or
> > disallows this?
> A pointer-to-char is not the same as an array of char. 8.3.4 states "an
> object of array type contains a contiguously allocated non-empty set of
> N sub-objects of type T." So I'd say if a compiler substituted a
> pointer for an array, it is not conforming.
True. 'sample' itself can't be a pointer. However, an object of type A
might contain a pointer to sample, rather than the actual storage for
'sample'. This wouldn't be legal for a POD class, but would be for a
non-POD class, which this is. A POD class must be an aggregate, and
therefore can have neither private members, nor a base class (8.5.1 p1).
'A' has both.
> ... Therefore, sizeof(A) is
> required to be a minimum of 50.
> > I want to make sure the whether the following things are true or not.
> > Any quote to the standard would be of big help.
....
> > 2. the address of each member of obj casted to const char* is in
> > between the address of obj and the address of obj plus sizeof(obj),
> > casted to char.
> In other words, something like this:
>
> struct T
> {
> int x, y, z;
> };
>
> void f()
> {
> T t;
> assert((char *)&t.x >= (char *)&t);
> assert((char *)&t.x < (char *)&t+sizeof(t));
> }
> and so on, right?
Not exactly. 'T' is a POD type, for which such guarantees exist. 'A'
isn't, so they don't.
> > Supplemental question: does this apply to base
> > classes? Supplementalmental (sic) question: does this apply to virtual
> > base classes?
> Good question. I didn't see anything in the Standard which would
> preclude an implementation from using a pointer to a base class instead
> of including the base class directly, e.g.:
And the same is true of the data members of the derived class.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 2000/05/10 Raw View
In article <MPG.1380d4af1604e6eb989870@news.mindspring.com>,
Jerry Coffin <jcoffin@taeus.com> wrote:
[snip]
> Looking through things, I spotted one thing I _think_ may be an error
> (though I haven't looked through the core-language issue list to see
> if it's already been noted). Section 1.8/5 says that "an object of
> POD type (3.9) shall occupy contiguous bytes of storage." I believe
> the intent of POD types is that they be be layout-compatible with C
> types (e.g. a legal C struct definition compiled as C++ should retain
> essentially the same layout). The members of a C struct, however,
> are not required to be contiguous -- they're required to be allocated
> in ascending order, but may have padding between them.
1.8 is not incompatible with padding - it does not state that the
sub-objects must be contiguous, just that the block occupied by the
object consists of a single block of contiguous memory. In other words,
it fits Andrei's requirement that for any member M of an instance of POD
object T you are guaranteed that:
((char *)(&T)) <= ((char *)(&T.M)) &&
((char *)(&T.M)) < ((char *)((&T)+sizeof(T)))
--
Jim
I ignore all email from recruitment agencies. Except that
I reserve the right to send rude, nasty replies to recruiters.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 2000/05/09 Raw View
I know this is pretty darn silly, but I really need help and I guess
it's better to make a fool of myself, than shutting my mouth up and
remaining shaded by the darkness of obscurantism.
I formulated a similar question in clc++m, but unfortunately didn't
get enough answers. I'll try to be more cunning here so as to attract
more interest and therefore more answers. It all depends on how you
ask the question :o).
It's all very simple (cunning, huh?). I have a little class.
class A : public Base
{
char sample[50];
...
};
My question is: what portable assumptions can I make about the size
and the layout of A in memory?
I want to make it clear that I'm not lazy. I did my homework - I
looked in the standard, but somehow I always have trouble verifying
integrating questions like that. I found some implications in 3.9.2/1,
Compound Types. There the doc says classes contain "a sequence of
objects of various types". But that's not enough. 9.2/12 makes
interesting statements, but again it's all not crystal-clear.
Is there a guarantee that says A aggregates A::sample directly? For
instance, a C++ interpreter could store a pointer to A::sample inside
A, instead of storing the fifty characters. In this case, sizeof(A) is
not necessarily greater than sizeof(A().sample). Would that be a
conforming C++ implementation? What part of the standard allows or
disallows this?
I want to make sure the whether the following things are true or not.
Any quote to the standard would be of big help.
1. sizeof(obj) is greater than or equal to the sum of all its direct
members.
2. the address of each member of obj casted to const char* is in
between the address of obj and the address of obj plus sizeof(obj),
casted to char. Supplemental question: does this apply to base
classes? Supplementalmental (sic) question: does this apply to virtual
base classes?
In other words: is an object a comprehensive, inclusive storage for
all of its bases and members? By reading the standard, I feel this is
implied in a lot of places, but I didn't find a place where that's
stated bluntly. Well, I need that blunt statement.
Any help would be greatly appreciated.
Andrei
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]