Подтвердить что ты не робот

С++: время жизни объекта и внешние функции

Предположим, что я хочу вызвать внешнюю функцию моего объекта для выполнения некоторых проверок внутри конструктора body. Поскольку срок жизни объекта начинается, когда тело конструктора заканчивает выполнение, является ли это небезопасным дизайном?

struct A;

void check(A const&) { /* */ }

struct A
{
    A() { check(*this); }
};

Я имею в виду, я вызываю и внешнюю функцию с еще не живым объектом. Это поведение undefined?

Связанные вопросы: если я поместил эту функцию проверки как функцию-член (статический или нет), что говорит стандарт об использовании объектов, не являющихся еще живыми вне конструктора, но внутри класса?

Есть ли какая-то разница в концепции жизни между точкой зрения класса и его пользователями (что-то вроде жизни класса или вне класса)?

4b9b3361

Ответ 1

Время жизни A не будет начато при вызове check(), потому что из [base.life]:

Время жизни объекта типа T начинается, когда:

  • с правильной настройкой и размером для типа T, и
  • Если объект имеет незапамятную инициализацию, его инициализация завершена.

A имеет непустую инициализацию. Его инициализация завершена, когда из [class.base.init]/13:

В конструкторе без делегирования инициализация выполняется в следующем порядке:

  • ...
  • - Наконец, выполняется составная инструкция тела конструктора.

Однако, несмотря на то, что A не имеет своего срока службы, стандарт дополнительно предоставляет в [class.base.init]/16:

Функции-члены (в том числе функции виртуальных членов, 10.3) могут быть вызваны для строящегося объекта... Однако, если эти операции выполняются в ctor-инициализаторе (или в функции, называемой непосредственно или косвенно из ctor-инициализатора) до того, как все инициализаторы mem для базовых классов завершены, результатом операции является undefined.

Что касается вопросов, касающихся жизни, нет никакой разницы между:

void check(const A& ) { .. }
struct A { 
    A() { check(*this); } 
};

и

struct A {
    void check() const { .. }
    A() { check(); }
};

Последнее явно разрешено (как это не в ctor-инициализаторе), поэтому я не вижу оснований для исключения первого на всю жизнь.