The constructs in a C++ program create, destroy, refer to, access, and
manipulate objects
. [
Note 1:
A function is not an object, regardless of whether or not it
occupies storage in the way that objects do
. —
end note]
The properties of an
object are determined when the object is created
. [
Note 2:
Some objects are
polymorphic (
[class.virtual]); the implementation
generates information associated with each such object that makes it
possible to determine that object's type during program execution
. —
end note]
An object that is not a subobject of any other object is called a
complete
object. If an object is created
in storage associated with a subobject
e
(which may or may not be within its lifetime),
the created object
is a subobject of
e's containing object if
- the lifetime of e's containing object has begun and not ended, and
- the storage for the new object exactly overlays the storage location associated with e, and
- e is not a potentially-overlapping subobject, and
- the new object is of the same type as e (ignoring cv-qualification).
If a complete object is created (
[expr.new])
in storage associated with another object
e
of type “array of
N unsigned char” or
of type “array of N std::byte” ([cstddef.syn]),
that array provides storage
for the created object if
- the lifetime of e has begun and not ended, and
- the storage for the new object fits entirely within e, and
- there is no array object that satisfies these constraints nested within e.
[
Note 3:
If that portion of the array
previously provided storage for another object,
the lifetime of that object ends
because its storage was reused (
[basic.life])
. —
end note]
[
Example 1:
template<typename ..T>
struct AlignedUnion {
alignas(T..) unsigned char data[max(sizeof(T).)];
};
int f() {
AlignedUnion<int, char> au;
int *p = new (au.data) int;
char *c = new (au.data) char();
char *d = new (au.data + 1) char();
return *c + *d;
}
struct A { unsigned char a[32]; };
struct B { unsigned char b[16]; };
alignas(int) A a;
B *b = new (a.a + 8) B;
int *p = new (b->b + 4) int;
—
end example]
An object
a is
nested within another object
b if
- a is a subobject of b, or
- b provides storage for a, or
- there exists an object c
where a is nested within c,
and c is nested within b.
For every object
x, there is some object called the
complete object of x, determined as follows:
If
x is a complete object, then the complete object
of
x is itself
.Otherwise, the complete object of
x is the complete object
of the (unique) object that contains
x.If a complete object, a member subobject, or an array element is of
class type, its type is considered the
most derived
class, to distinguish it from the class type of any base class subobject;
an object of a most derived class type or of a non-class type is called a
most derived object.An object has nonzero size if it
- is not a potentially-overlapping subobject, or
- is not of class type, or
- is of a class type with virtual member functions or virtual base classes, or
- has subobjects of nonzero size or unnamed bit-fields of nonzero length.
Otherwise, if the object is a base class subobject
of a standard-layout class type
with no non-static data members,
it has zero size
. Otherwise, the circumstances under which the object has zero size
are
implementation-defined
. Unless it is a
bit-field,
an object with nonzero size
shall occupy one or more bytes of storage,
including every byte that is occupied in full or in part
by any of its subobjects
. An object of trivially copyable or
standard-layout type (
[basic.types.general]) shall occupy contiguous bytes of
storage
.Unless an object is a bit-field or a subobject of zero size, the
address of that object is the address of the first byte it occupies
. Two objects
with overlapping lifetimes
that are not bit-fields
may have the same address if
- one is nested within the other,
- at least one is a subobject of zero size and they are not of similar types ([conv.qual]),
or
- they are both potentially non-unique objects;
otherwise, they have distinct addresses
and occupy disjoint bytes of storage
. [
Example 2:
static const char test1 = 'x';
static const char test2 = 'x';
const bool b = &test1 != &test2;
static const char (&r) [] = "x";
static const char *s = "x";
static std::initializer_list<char> il = { 'x' };
const bool b2 = r != il.begin();
const bool b3 = r != s;
const bool b4 = il.begin() != &test1;
const bool b5 = r != &test1;
—
end example]
The address of a subobject of zero size is
the address of an unspecified byte of storage
occupied by the complete object of that subobject
.The
constituent values of an object
o are
- if o has scalar type, the value of o;
- otherwise, the constituent values of any direct subobjects of o
other than inactive union members.
The
constituent references of an object
o are
- any direct members of o that have reference type, and
- the constituent references of any direct subobjects of o
other than inactive union members.
For each operation that is specified as implicitly creating objects,
that operation implicitly creates and starts the lifetime of
zero or more objects of implicit-lifetime types (
[basic.types.general])
in its specified region of storage
if doing so would result in the program having defined behavior
. If no such set of objects would give the program defined behavior,
the behavior of the program is undefined
. If multiple such sets of objects would give the program defined behavior,
it is unspecified which such set of objects is created
. [
Note 4:
Such operations do not start the lifetimes of subobjects of such objects
that are not themselves of implicit-lifetime types
. —
end note]
Further, after implicitly creating objects within a specified region of storage,
some operations are described as producing a pointer to a
suitable created object. These operations select one of the implicitly-created objects
whose address is the address of the start of the region of storage,
and produce a pointer value that points to that object,
if that value would result in the program having defined behavior
. If no such pointer value would give the program defined behavior,
the behavior of the program is undefined
. If multiple such pointer values would give the program defined behavior,
it is unspecified which such pointer value is produced
.[
Example 3:
#include <cstdlib>
struct X { int a, b; };
X *make_x() {
X *p = (X*)std::malloc(sizeof(struct X));
p->a = 1;
p->b = 2;
return p;
}
—
end example]
Except during constant evaluation,
an operation that begins the lifetime of
an array of
unsigned char or
std::byte
implicitly creates objects within the region of storage occupied by the array
. [
Note 5:
The array object provides storage for these objects
. —
end note]
Except during constant evaluation,
any implicit or explicit invocation of a function
named
operator new or operator new[]
implicitly creates objects in the returned region of storage and
returns a pointer to a suitable created object.