Title
Multiple objects of the same type at the same address
Status
tentatively ready
Section
6.8.2 [intro.object]
Submitter
Chris Hallock

Created on 2023-06-08.00:00:00 last changed 1 month ago

Messages

Date: 2026-02-06.22:00:31

Proposed resolution (approved by CWG 2026-02-06):

Change in 6.8.2 [intro.object] paragraph 10 as follows:

... Two objects with overlapping lifetimes that are not bit-fields may have the same address if
  • one is nested within the other,
  • they are both nested within some complete object o, exactly one is a subobject of o, and the subobject is of zero size,
  • they are both subobjects of the same complete object, at least one is a subobject of zero size, and they are not of similar types (7.3.6 [conv.qual]), or
  • they are both potentially non-unique objects;
otherwise, they have distinct addresses and occupy disjoint bytes of storage. [ Footnote: ... ]
Date: 2026-01-23.23:48:07

Additional notes (CWG 2026-01-23):

Consider:
  A x{}: // implicit object creation for x.buf
  A* p = reinterpret_cast<A*>(x.buf); // nailed down A at x.buf

There is no pointer interconvertibility between x.buf and x, so there must be a second A at x.buf.

Also consider:
  struct S {
    unsigned char c[1];
  };
  unsigned char a[sizeof(S)];
  S* ps = new (a) S;  // must create S inside a buffer; now we have two "array of unsigned char" at the same address
Also consider:
  struct B {};
  struct A : B {};
  struct C : B {};
  struct D : A, C { unsigned char x[2]; };

  D d;
  new (d.x+1) C();

The A and C base classes must have different offsets (because their B bases must have different offsets), thus #2 creates a C object at the offset of the existing C base class object.

CWG leaned towards adding a targeted exception that two objects of the same type may be located at the same address if both are nested within the same complete object.

Date: 2026-01-23.23:48:07

Suggested resolution [SUPERSEDED]:

Change in 6.8.2 [intro.object] paragraph 3 as follows:

If a complete object of type T is created (7.6.2.8 [expr.new]) in storage associated with another object e of type “array of N unsigned char” or of type “array of N std::byte” (17.2.1 [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
  • e is not and is not nested within an object of type similar (7.3.6 [conv.qual]) to T that is within its lifetime, and
  • there is no array object that satisfies these constraints nested within e.
Date: 2023-06-08.00:00:00

(From thread beginning here.)

Consider:

  #include <new>

  struct A { unsigned char buf[1]; };
  static_assert(sizeof(A) == 1); // A can fit within A::buf

  int main()
  {
    A x{};
    new (x.buf) A{};
  }

A::buf provides storage for another A object. Thus, there are now two objects of type A within lifetime, which is inconsistent with the goal expressed by 6.8.2 [intro.object] paragraph 9.

History
Date User Action Args
2026-02-06 22:00:31adminsetstatus: open -> tentatively ready
2026-01-23 23:48:07adminsetmessages: + msg8463
2026-01-23 19:03:24adminsetmessages: + msg8461
2023-06-09 07:14:31adminsetmessages: + msg7308
2023-06-08 00:00:00admincreate