4 General principles [intro]

4.5 The C++ object model [intro.object]

Конструкции в программе C ++ создают, уничтожают, обращаются к объектам, обращаются к ним и манипулируют ими. An object создается a definition, a new-expression, при неявном изменении активного члена a unionили при создании временного объекта ([conv.rval], [class.temporary]). Объект занимает область хранения в период постройки ([class.cdtor]), в течение всего lifetimeпериода и в период разрушения ([class.cdtor]). [ Note: Функция не является объектом, независимо от того, занимает ли она память так, как это делают объекты. ] Свойства объекта определяются при создании объекта. Объект может иметь расширение . У объекта есть влияющий на него объект . Объект имеет расширение . Некоторые объекты есть ; реализация генерирует информацию, связанную с каждым таким объектом, которая позволяет определить тип этого объекта во время выполнения программы. Для других объектов интерпретация найденных в них значений определяется типом (раздела ), используемого для доступа к ним. end notenamestorage duration lifetimetypepolymorphicexpressions [expr]

Объекты могут содержать другие объекты, называемые subobjects. Подобъектом может быть member subobject ([class.mem]), base class subobject (Предложение [class.derived]) или элемент массива. Объект, который не является подобъектом какого-либо другого объекта, называется complete object. Если объект создается в хранилище, связанном с подобъектом-членом или элементом массива e (который может находиться или не находиться в пределах его жизненного цикла), созданный объект является подобъектом eсодержащего его объекта, если:

  • время жизни eсодержащего объекта началось и не закончилось, и

  • хранилище для нового объекта точно перекрывает местоположение хранилища, связанное с e, и

  • новый объект того же типа, что и e (игнорируя cv-квалификацию).

[ Note: Если подобъект содержит ссылочный элемент или const подобъект, имя исходного подобъекта нельзя использовать для доступа к новому объекту ([basic.life]). ] [end noteExample:

struct X { const int n; };
union U { X x; float f; };
void tong() {
  U u = {{ 1 }};
  u.f = 5.f;                          // OK, creates new subobject of u ([class.union])
  X *p = new (&u.x) X {2};            // OK, creates new subobject of u
  assert(p->n == 2);                  // OK
  assert(*std::launder(&u.x.n) == 2); // OK
  assert(u.x.n == 2);                 // undefined behavior, u.x does not name new subobject
}

end example]

Если[expr.new]в хранилище создается полный объект ( ), связанный с другим объектом e типа «массив N unsigned char» или типа «массив N std​::​byte» ([cstddef.syn]), этот массив provides storage для созданного объекта, если:

  • время жизни e началось и не закончилось, и

  • хранилище для нового объекта полностью помещается внутри e, и

  • не существует меньшего объекта массива, удовлетворяющего этим ограничениям.

[ Note: Если эта часть массива ранее предоставляла хранилище для другого объекта, время существования этого объекта заканчивается, поскольку его хранилище было повторно использовано ([basic.life]). ] [end noteExample:

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;     // OK, au.data provides storage
  char *c = new (au.data) char(); // OK, ends lifetime of *p
  char *d = new (au.data + 1) char();
  return *c + *d; // OK
}

struct A { unsigned char a[32]; };
struct B { unsigned char b[16]; };
A a;
B *b = new (a.a + 8) B;      // a.a provides storage for *b
int *p = new (b->b + 4) int; // b->b provides storage for *p
                             // a.a does not provide storage for *p (directly),
                             // but *p is nested within a (see below)

end example]

Объект a - это nested within другой объект, b если:

  • a является подобъектом b, или

  • b обеспечивает хранение a, или

  • существует объект , c где a вложен в cи c вложен в b.

Для каждого объекта xсуществует объект, называемый the complete object of x, который определяется следующим образом:

  • Если x это законченный объект, то полный объект x - это сам.

  • В противном случае полный объект x является полным объектом (уникального) объекта, который содержит x.

Если полный объект, a data memberили элемент массива относятся к типу класса, его тип считается most derived class, чтобы отличить его от типа класса любого подобъекта базового класса; объект самого производного типа класса или неклассового типа называется most derived object.

Если это не a bit-field, наиболее производный объект должен иметь ненулевой размер и занимать один или несколько байтов памяти. Подобъекты базового класса могут иметь нулевой размер. Объект тривиально копируемый или standard-layout type должен занимать непрерывные байты памяти.

Если объект не является битовым полем или подобъектом базового класса нулевого размера, адрес этого объекта является адресом первого байта, который он занимает. Два объекта a и b с перекрывающимися временами жизни, которые не являются битовыми полями, могут иметь один и тот же адрес, если один вложен в другой, или если хотя бы один является подобъектом базового класса нулевого размера и они относятся к разным типам; в противном случае у них разные адреса.5

[Example:

static const char test1 = 'x';
static const char test2 = 'x';
const bool b = &test1 != &test2;      // always true

end example]

[ Note: C ++ предоставляет множество основных типов и несколько способов создания новых типов из существующих типов ([basic.types]). ]end note

По правилу «как если бы» реализации разрешено хранить два объекта по одному и тому же машинному адресу или не хранить объект вообще, если программа не может заметить разницу ([intro.execution]).