Разница в правилах конца жизни? - PullRequest
0 голосов
/ 14 декабря 2018

https://en.cppreference.com/w/cpp/language/lifetime в Примечания * В разделе есть этот код, воспроизведенный здесь:

struct A {
  int* p;
  ~A() { std::cout << *p; } // if n outlives a, prints 123
};
void f() {
  A a;
  int n = 123; // if n does not outlive a, this is optimized out (dead store)
  a.p = &n;
}

Что он пытается сказать в этом разделе Примечания ?

Из того, что я понимаю, код UB (или он есть), поскольку ясно, что n не переживает a.

Что это означает:

разница в правилах окончания срока службы между объектами, не относящимися к классу (срок хранения) и объектами класса (обратный порядок построения), имеет значение

Но это не означает, что значение как .

Я очень смущен всем этим разделом.

Ответы [ 2 ]

0 голосов
/ 15 декабря 2018

Этот пример заимствован из Базовая языковая проблема 2256 :

Раздел: 6,8 [basic.life] Статус: Составление Отправитель: Ричард Смит Дата: 2016-03-30

Согласно п. 1.4 [basic.lookup] 6.4, в следующем примере определено поведение, поскольку время жизниn продолжается до освобождения хранилища, то есть после запуска деструктора a:

  void f() { 
    struct A { int *p; ~A() { *p = 0; } } a; 
    int n; 
    a.p = &n; 
  } 

Было бы более согласованным, если бы закончился срок жизни всех объектов, независимо от того, являются ли ониимеют нетривиальный деструктор, с ним обращались одинаково.

Примечания от встречи в марте 2018 года:

CWG согласилась с предложенным указанием.

Ключевая идея заключается в том, может ли время жизни объекта закончиться при его разрушении или в момент освобождения его памяти, может повлиять на семантику программы.В этом примере

  1. , если время жизни n заканчивается при уничтожении n, программа не определена;

  2. , есливремя жизни n заканчивается, пока память не будет освобождена, программа определила поведение 1 .

Следовательно, требуется дальнейшее обсуждение, чтобы определить, когда время жизниобъект заканчивается.


1 Это потому, что Базовая языковая проблема 2115 :

Раздел: 9,6 [stmt.jump] Статус: Составление Отправитель: Ричард Смит Дата: 2015-04-16

Относительное упорядочение между уничтожением автоматических переменных навыход из блока и освобождение хранилища переменных не определено Стандартом: выполняются ли сначала все деструкторы, а затем освобождается хранилище, или они чередуются?

Примечания за февраль,Совещание 2016 года:

CWG решила, что хранилище должно сохраняться до тех пор, пока все разрушения не будут завершены, хотя правило «как если бы» позволяло проводить ненаблюдаемую оптимизацию этого порядка.

Намерение состоит в том, что освобождение памяти автоматических переменных происходит после завершения всех разрушений.

0 голосов
/ 14 декабря 2018

Это странный аспект правил жизни C ++. [basic.life] / 1 сообщает нам , что время жизни объекта заканчивается:

  • , если T - это тип класса с нетривиальным деструктором ([class.dtor]), начинается вызов деструктора, или
  • хранилище, которое занимает объект, освобождается или повторно используется объектом, который не вложен в o ([intro.object]).

Акцент добавлен.int не является «типом класса с нетривиальным деструктором», поэтому его время жизни заканчивается только когда освобождается занимаемое им хранилище.Напротив, A является типом класса с нетривиальным деструктором ", поэтому его время жизни заканчивается, когда вызывается деструктор.

Хранилище для области освобождается при выходе из области в соответствии с [basic.stc.auto] / 1 :

Хранение [переменных с автоматическим хранением] длится до выхода из блока, в котором они созданы.

Но автоматические переменные уничтожаются в соответствии с [stmt.jump] / 2 :

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

Обратите внимание, что указан порядок уничтожения, но порядок автоматического освобождения хранилища равен , а не .Это означает, что реализация может освободить хранилище сразу после уничтожения каждой переменной, либо освободить все сразу, либо в произвольном другом порядке.

Теперь,тот факт, что он использует единственное число для хранения («хранилище для ... длится») вместо того, чтобы говорить о каждой переменной в отдельности, может указывать на то, что цель состоит в том, чтобы хранилище в целом было сразу освобождено для этой области.Но в стандарте нет явного заявления об этом.Таким образом, до тех пор, пока переменная уничтожается до освобождения ее хранилища, любой порядок уничтожения и выпуска представляется законным.

Это означает, что код может полностью работать, а n пережитьa.Но неизвестно, работает ли .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...