Namespaces
Variants

Lifetime

From cppreference.net

Каждый объект в C существует, имеет постоянный адрес, сохраняет последнее записанное значение (кроме случаев, когда значение неопределено) , и, для VLA, сохраняет свой размер (начиная с C99) в течение части выполнения программы, известной как время жизни этого объекта.

Для объектов, объявленных с автоматической, статической и потоковой длительностью хранения, время жизни равно их storage duration (обратите внимание на разницу между не-VLA и VLA automatic storage duration).

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

Доступ к объекту за пределами его времени жизни является неопределённым поведением.

int* foo(void) {
    int a = 17; // переменная a имеет автоматическую продолжительность хранения
    return &a;
}  // время жизни a завершается
int main(void) {
    int* p = foo(); // p указывает на объект после завершения времени жизни ("висячий указатель")
    int n = *p; // неопределённое поведение
}

Указатель на объект (или за его пределами), время жизни которого завершилось, имеет неопределённое значение.

Время жизни временных объектов

Объекты структур и объединений с элементами-массивами (прямыми или членами вложенных структур/объединений), которые обозначаются не-lvalue выражениями , имеют временное время жизни . Временное время жизни начинается при вычислении выражения, ссылающегося на такой объект, и заканчивается в следующей точке следования (до C11) при завершении содержащего полного выражения или полного декларатора (начиная с C11) .

Любая попытка модификации объекта с временным временем жизни приводит к неопределённому поведению.

struct T { double a[4]; };
struct T f(void) { return (struct T){3.15}; }
double g1(double* x) { return *x; }
void g2(double* x) { *x = 1.0; }
int main(void)
{
    double d = g1(f().a); // C99: НО обращение к a[0] в g1, время жизни которого завершилось
                          //      в точке следования в начале g1
                          // C11: OK, d равно 3.15
    g2(f().a); // C99: НО модификация a[0], время жизни которого завершилось в точке следования
               // C11: НО попытка модификации временного объекта
}

Ссылки

  • Стандарт C17 (ISO/IEC 9899:2018):
  • 6.2.4 Время жизни объектов (стр: 30)
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 6.2.4 Время жизни объектов (стр. 38-39)
  • Стандарт C99 (ISO/IEC 9899:1999):
  • 6.2.4 Время жизни объектов (стр. 32)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
  • 3.1.2.4 Время хранения объектов

Смотрите также

Документация C++ для Время жизни объекта