Topic: why does POD matter?
Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: 1999/09/15 Raw View
[I've posted the following message to comp.std.c++ twice now; once on
1999-09-02, and the second time on 1999-09-09. I've yet to see either
message appear on the newsgroup, nor have I received any message
indicating that the moderators had rejected it. Neither copy appears on
Deja News.]
[ moderator's note: I never saw the originals. Maybe there's a
problem with the configuration of your news server. -sdc ]
Jeffrey Juliano wrote:
...
> Sound right? Any other reason why I'd care if something is POD?
Yes - the standard makes some guarantees about POD's. If you want to
write code that depends upon one or more of those guarantees, you need
to know whether your class is a POD. Specifically:
1.8 p5: POD's occupy contiguous storage
3.6.2 p1: static POD's "shall be initialized before any dynamic
initialization takes place"
3.8 p5: During the time that memory has been allocated for a POD object,
but outside it's lifetime, it is NOT undefined behavior to use a pointer
to that memory
- to access a non-static data member or call a non-static
member function
- as the operand of a static_cast<>
3.8 p6: says similar things to 3.8 p5 about lvalues.
3.9 p2: the contents of a POD object can be copied to a sufficiently
large array of 'char' or 'unsigned char' and back again without changing
the value of the object
3.9 p3: the contents of a POD can be copied using memcpy() to another
object of the same type; the value of the second object will be the same
as the value of the first.
5.2.2 p7: a POD object can be passed as one of the variable arguments of
a function
5.3.15 p15: a new-expression doesn't have to waste time initializing a
POD object of class type.
5.19 p4: the address of a POD member can be an address constant
expression.
5.19 p5: a reference to a POD member can be a reference constant
expression.
6.7 p3: you can jump from a place where a local automatic POD object is
not in scope, to one where it is in scope, so long as that object is
declared without an initializer.
6.7 p4: a local static POD object declared with initializers is
initialized before its block is first entered.
8.5 p5: default initialization of a POD object is zero initialization.
8.5 p9: if no initializer is specified for a POD, no initialization need
be done.
8.5.1 p14: if a static aggregate POD's initializers are constant
expressions, initialization occurs during the static phase of
initialization.
9.2 p14: "Two POD-struct types are layout-compatible if they have the
same number of members, and corresponding members (in order) have layout
compatible types"
9.2 p15: Similar statement about POD-unions.
9.2 p16: "If a POD-union contains two or more POD-structs that share a
common initial sequence, and if the POD-union contains one of these
POD-structs, it is permitted to inspect the common initial part of any
of them."
9.2 p17: "A pointer to a POD-struct, suitably converted using a
reinterpret_cast, points to its initial member (of if that member is a
bit-field, then to the unit in which it resides) and vice versa."
21 p1: Any POD type may be used as the "character" type in the
standard's templated string classes.
None of the above things are guaranteed for non-POD types. Now, your
code might not depend upon any of these guarantees, but it's not unusual
to write code that depends upon at least one of them. In that case, it's
a good idea to be aware what types of objects those guarantees actually
apply to.
[ 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: "Marco Dalla Gasperina" <marcodg@pacifier.com>
Date: 1999/09/09 Raw View
Jim Hyslop <jim.hyslop@leitch.com> wrote in message
news:7r8f10$da4$1@nnrp1.deja.com...
> There is one subtle distinction between POD and non-POD when allocating
> them dynamically. Given this statement:
>
> T * tInstance = new T;
>
> If T is a POD, tInstance will not be initialized. If T is not a POD,
> tInstance will be default-initialized.
>
And,
T * tInstance = new T();
should always default initialize the object even if its a POD (meaning
that member variables are initialized to 0/NULL etc).
Don't be surprised if your compiler doesn't quite get this one
right (having been bit by it in the past).
marco
---
[ 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: 1999/09/09 Raw View
In article <slrn7srr33.r1d.juliano@capefear.cs.unc.edu>,
juliano@cs.unc.edu (Jeffrey Juliano) wrote:
[snip]
>
> I've been trying to figure out what POD really means, and why I
> should/shouldn't care. After reading a bunch of posts in the deja
> logs, I've come to the following conclusions. Someone please correct
> me if I'm wrong, or point out important points that I've missed.
[snip]
There is one subtle distinction between POD and non-POD when allocating
them dynamically. Given this statement:
T * tInstance = new T;
If T is a POD, tInstance will not be initialized. If T is not a POD,
tInstance will be default-initialized.
--
Jim
I ignore all email from recruitment agencies.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ 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 Biggar <jon@floorboard.com>
Date: 1999/09/02 Raw View
Jeffrey Juliano wrote:
>
> [note to moderator: if this is off-topic, I'll post to
> comp.lang.c++.moderated instead]
>
> [ moderator's note: comp.std.c++ is for discussion of the standard
> and its provisions, and reasons for them, among other things.
> Discussion of PODs is entirely on topic. -sdc ]
>
> I've been trying to figure out what POD really means, and why I
> should/shouldn't care. After reading a bunch of posts in the deja
> logs, I've come to the following conclusions. Someone please correct
> me if I'm wrong, or point out important points that I've missed.
>
> * POD means compatibility with C structs
...
> Sound right? Any other reason why I'd care if something is POD?
In many environments static PODs that are initialized via an aggregate
are effectively initialized at compile time, and consume zero run time
for initialization. For programs with lots of static data, this can be
a big win at start-up time.
--
Jon Biggar
Floorboard Software
jon@floorboard.com
jon@biggar.org
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/03 Raw View
Jeffrey Juliano <juliano@cs.unc.edu> wrote:
> I've been trying to figure out what POD really means, and why I
> should/shouldn't care. After reading a bunch of posts in the deja
> logs, I've come to the following conclusions. Someone please correct
> me if I'm wrong, or point out important points that I've missed.
Here's my understanding.
Like most language features, the precise definition of POD matters more to
someone writing a compiler than to a programmer writing C++ code. For most
programmers' purposes, a rule of thumb can be, "If I could have defined this
in exactly this way in C, then I can do C-like things with it. If I used
anything C++-specific, then I better not."
The idea is to define which objects (not just structs) require compatibility
with certain C coding practices. The compiler must keep these coding
practices working, including copying an object with memcpy and many others,
for anything that meets the standard's definition of an object of POD type.
For other objects, the compiler can break this C compatibility if there's a
reason (efficiency, perhaps, or simply the implementation of things like
virtual functions and references).
Thus when you tread outside the POD line the compiler has the freedom to do
things that would make the C idiom fail. For compatibility with C, anything
made with only C constructs ends up as a POD (that's a rough summary, not a
precise expression of what's in the standard).
> * POD means compatibility with C structs
There are many kinds of objects that have POD type, not just structs.
> [So, if I don't care about compatability with C, should I not care if
> any of my structs are POD?]
As long as you are not doing C-ish things that are guaranteed to work only
with objects of POD type, you don't care if your structs are POD.
Some of these C-ish things are: using memcpy to copy the object (3.9p3),
using memcpy to copy the object into an array of char and back (3.9p2),
assuming the bytes of storage for the object are contiguous (1.8p5),
assuming that a global object is initialized before any code is executed
(3.6.2p1), using a pointer before the object is initialized (3.8p5), passing
the object as an argument to a function with a variable number of parameters
(5.2.2p7), using a goto past the declaration of a local variable (6.7p3).
There are others.
For some of these operations, it's clear that they wouldn't work for classes
with virtual functions. But the standard goes further and says that they are
only guaranteed to work for objects of POD type, an even smaller set.
> * specifically, the layout is guaranteed to be the same if the defn
> of the struct is read by a C or a C++ compiler, sans any member
> functions. This allows you to transfer data between object files
> compiled on a C and a C++ compiler. (have to be same vendor, or
> no?)
The standard doesn't contain guarantees about POD-struct layout being the
same as a "compatible C compiler". C compatibility guaranteed by the
standard is compatibility with C code that's compiled with the C++ compiler,
not code compiled by a separate C compiler.
On the other hand, you might find that if you are trying to mix data
structures between a C compiler and a C++ compiler, you'd have better luck
if you stick to POD types, even though the standard says nothing about this.
> * To make this possible, you cannot add
>
> * non-pod struct or union as data member
Any non-POD-type object as a data member will prevent the struct from being
a POD-struct. This object need not be a struct or union. One example: If you
have a data member of reference type, then the struct is not a POD-struct.
> * non-static reference or ptr-to-member-funct data
> (doesn't exist in C)
>
> * virtual member functions, because, at least in the common
> implementation, that will introduce a vtable
>
> * virtual destructor (same thing)
> [side question: is a destructor a member function,
> or is it a special case like a constructor is?]
>
> * In order to keep the in C++ as in C code when an instance of a
> POD is used (in ways that are valid in C), you cannot have
>
> * destructor (any, actually)
>
> * copy assignment operator
Any of these would definitely prevent a struct from being a POD-struct.
> [Do I have the right reason for these last two restrictions?]
The standard doesn't state a reason. Nor does it have to.
However, I believe the main reason is that you can't do these things in C
code, so the standard doesn't have to require compatibility with C coding
practices for structures that use these features. To give the creator of a
compiler maximum freedom, the standard allows the compiler to do
optimizations that would violate some of the C-compatibility assumptions
once you cross the line from POD-struct to non-POD-struct.
> * but, you are allowed to have
>
> * constructors
Nope.
A struct with a user-defined constructor is not an aggregate (8.5.1p1), thus
it's not a POD-struct. So you are not allowed to have user-defined
constructors in a struct if you want the struct type to be a POD type.
> * non-virtual member functions other than destructor
Yes.
These member functions won't turn a POD-struct into a non-POD-struct. I
think it's nice that you can add member functions without losing some of the
C compatibility for manipulating the data.
Note that the list above is not exhaustive. For example, a protected or
private non-static data member is not allowed in a POD-struct, and a
POD-struct can't have any base classes. The place to find these rules in the
standard is the definition of POD type (3.9p10), of POD-struct and POD-union
(9p4), and of aggregates of class type (8.5.1p1).
> [These are not allowed in C in the first place, and don't cause
> problems with data layout.]
That's part of the issue. The other part is a partly-arbitrary line drawn by
the C++ standard, to allow possible optimizations that would break
compatibility for certain C coding practices.
> Sound right? Any other reason why I'd care if something is POD?
There are a number of different reasons, but few of them have anything to do
with normal C++ coding practices. The reasons all have to do with defining
precisely when certain C practices are legal in a C++ program. The concept
is to have enough to be compatible with existing C code, but not so much
that it becomes an unnecessary restriction for C++ compiler creators.
-- Darin
---
[ 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: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 1999/09/03 Raw View
juliano@cs.unc.edu (Jeffrey Juliano) writes:
> * POD means compatibility with C structs
>
> [So, if I don't care about compatability with C, should I not care if
> any of my structs are POD?]
POD types are not only structs, but also integral types and unions.
Also, POD is there not only for compatibility with C.
> * specifically, the layout is guaranteed to be the same if the defn
> of the struct is read by a C or a C++ compiler, sans any member
> functions. This allows you to transfer data between object files
> compiled on a C and a C++ compiler. (have to be same vendor, or
> no?)
That would depend on the ABI. The C++ standard itself does not define
interoperability between C and C++.
> [Do I have the right reason for these last two restrictions?]
>
> * but, you are allowed to have
>
> * constructors
A POD struct is an aggregate (with restrictions); according to
8.5.1/1, aggregates don't have user-defined constructors. Also, you
can't have base classes, either.
> Any other reason why I'd care if something is POD?
A number of additional guarantees are given for POD:
- you can initialize them with memcpy (i.e byte-wise). This means they
shouldn't have a user-defined initialization procedure, and they
shall occupy a continuous area in memory.
- They can be initialized in the {} aggregate notation (or appropriate
constant expression). If they are globals, such initializations are
guaranteed to happen before constuctors. Therefore, they don't
suffer from the initialization order problems.
- You can pass them through ...
- Converting an appropriate reinterpret_cast to a POD struct gives you
the pointer to its initial member.
- POD structs are not default-initialized in certain situations.
- You can use offsetof
- You can access a branch of a POD union even if that is not the
active one, provided that that other branch has a common initial
sequence with the current branch.
- You can initialize an object of a POD type with an object of another
POD type (using byte-wise copying), provided that the types are
layout-compatible.
Hope this helps,
Martin
---
[ 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: juliano@cs.unc.edu (Jeffrey Juliano)
Date: 1999/09/02 Raw View
[note to moderator: if this is off-topic, I'll post to
comp.lang.c++.moderated instead]
[ moderator's note: comp.std.c++ is for discussion of the standard
and its provisions, and reasons for them, among other things.
Discussion of PODs is entirely on topic. -sdc ]
I've been trying to figure out what POD really means, and why I
should/shouldn't care. After reading a bunch of posts in the deja
logs, I've come to the following conclusions. Someone please correct
me if I'm wrong, or point out important points that I've missed.
* POD means compatibility with C structs
[So, if I don't care about compatability with C, should I not care if
any of my structs are POD?]
* specifically, the layout is guaranteed to be the same if the defn
of the struct is read by a C or a C++ compiler, sans any member
functions. This allows you to transfer data between object files
compiled on a C and a C++ compiler. (have to be same vendor, or
no?)
* To make this possible, you cannot add
* non-pod struct or union as data member
* non-static reference or ptr-to-member-funct data
(doesn't exist in C)
* virtual member functions, because, at least in the common
implementation, that will introduce a vtable
* virtual destructor (same thing)
[side question: is a destructor a member function,
or is it a special case like a constructor is?]
* In order to keep the in C++ as in C code when an instance of a
POD is used (in ways that are valid in C), you cannot have
* destructor (any, actually)
* copy assignment operator
[Do I have the right reason for these last two restrictions?]
* but, you are allowed to have
* constructors
* non-virtual member functions other than destructor
[These are not allowed in C in the first place, and don't cause
problems with data layout.]
Sound right? Any other reason why I'd care if something is POD?
thanks,
-jeff
[ 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@bbnplanet.com>
Date: 1999/09/03 Raw View
In article <slrn7srr33.r1d.juliano@capefear.cs.unc.edu>,
Jeffrey Juliano <juliano@cs.unc.edu> wrote:
> * specifically, the layout is guaranteed to be the same if the defn
> of the struct is read by a C or a C++ compiler, sans any member
> functions. This allows you to transfer data between object files
> compiled on a C and a C++ compiler. (have to be same vendor, or
> no?)
If you take a look at the discussion of packed structures, the answer to
your question should be pretty obvious. C doesn't require different
vendors to use the same structure layout, and PODs are only expected to be
equivalent to C, so they obviously can't be expected to be compatible
between different vendors, either.
Cross-vendor compatibility should be provided via an ABI for the
process/OS. If such a thing exists, PODs should conform to it, and then
you'll be able to transfer data between object files compiled with
different vendors' C and C++ compilers.
--
Barry Margolin, barmar@bbnplanet.com
GTE Internetworking, Powered by BBN, 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: "Greg Brewer" <nospam.greg@brewer.net>
Date: 1999/09/03 Raw View
Jeffrey Juliano <juliano@cs.unc.edu> wrote in message
news:slrn7srr33.r1d.juliano@capefear.cs.unc.edu...
> I've been trying to figure out what POD really means, and why I
> should/shouldn't care. After reading a bunch of posts in the deja
> logs, I've come to the following conclusions. Someone please correct
> me if I'm wrong, or point out important points that I've missed.
>
> * POD means compatibility with C structs
If memory serves, it means plain ole data. I think I can demonstrate better
than I can explain. Consider the following 3 class definitions:
class A {
int abc, def;
char buffer[256];
float *value;
int Fluff(void);
};
class B {
int abc, def;
char buffer[251];
float *value;
int Fluff(void);
virtual int Stuff(void);
};
class C : public A {
virtual int Stuff(void);
};
class A is a POD type class. class B and class C have hidden information
in a structure called a vtable. Now, here is some code that creates
instances and acts on those classes
A a;
memset(&a, 0, sizeof(A)); // no problem, will init to 0 including
any padding.
B b;
memset(&b, 0, sizeof(B)); // problem! this will wipe out the
vtable
C c;
memset(&c, 0, sizeof(C)); // problem! same as for B
A *aptr = &c;
memset(aptr, 0, sizeof(A)); // no problem, c's vtable will not be
touched.
Although I used memset, the same could be said of fread, fwrite and other
functions. The C++ standard allows the implementer great freedom in
handling the vtable; it is stricter about a POD structure. This has special
significance when dealing with the aptr case.
> [So, if I don't care about compatability with C, should I not care if
> any of my structs are POD?]
There are none C reason why having a POD base can be useful. Using the
definitions about, the following might be something you would want to do.
{
A saveData(c);
c.abc = 0;
int err = Validate(&c);
c = saveData;
if (c.abc > 99 && c.abc < 500)
err++;
return err;
}
In this case, the copy constructor was called upon to save then restore, the
data only components of the C class.
> * specifically, the layout is guaranteed to be the same if the defn
> of the struct is read by a C or a C++ compiler, sans any member
> functions. This allows you to transfer data between object files
> compiled on a C and a C++ compiler. (have to be same vendor, or
> no?)
Afraid not. Even same vendor is no guarentee that on the layout of a
structure.
> * To make this possible, you cannot add
>
> * non-pod struct or union as data member
There isn't a non-pod union. Also, you cannot have non-pod as a base class.
Pointers to these are okay.
> * non-static reference or ptr-to-member-funct data
> (doesn't exist in C)
It would still be POD.
> * virtual member functions, because, at least in the common
> implementation, that will introduce a vtable
yep.
> * virtual destructor (same thing)
> [side question: is a destructor a member function,
> or is it a special case like a constructor is?]
I think it counts as a member function.
> * In order to keep the in C++ as in C code when an instance of a
> POD is used (in ways that are valid in C), you cannot have
>
> * destructor (any, actually)
This is no problem if not virtual.
> * copy assignment operator
Again no problem
> [Do I have the right reason for these last two restrictions?]
>
> * but, you are allowed to have
>
> * constructors
>
> * non-virtual member functions other than destructor
>
> [These are not allowed in C in the first place, and don't cause
> problems with data layout.]
>
> Sound right? Any other reason why I'd care if something is POD?
A lot of the restrictions exist if you want to share data with a binary
compatible C. One thing a only recently learned you can do is
struct A {
// bunch of data declarations
};
class AA : public A {
};
Now, if A contains only C compatible data declarations. A C compiler can
process a header file that defines struct A but not class AA. I thought
this was going to be useful except I do a lot of
struct A {
enum {namesz=30};
char name[namesz+1];
};
which C won't process.
Greg Brewer
[ 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 ]