Мне трудно понять, как этот код (пример из проекта стандарта C ++ 14 [Conv.lval]) вызывает неопределенное поведение для g(false)
, Почему constexpr
сделать программу действительной?
Кроме того, что означает «не доступ y.n
«? В обоих звонках g()
мы возвращаем n
элемент данных, так почему последняя строка говорит, что не имеет к нему доступа?
struct S { int n; };
auto f() {
S x { 1 };
constexpr S y { 2 };
return [&](bool b) { return (b ? y : x).n; };
}
auto g = f();
int m = g(false); // undefined behavior due to access of x.n outside its
// lifetime
int n = g(true); // OK, does not access y.n
Это потому что y.n
не используется odr и поэтому не требует доступа к y.n
правила использования odr описаны в 3.2
и говорит:
Переменная x, имя которой появляется в качестве потенциально вычисляемого выражения ex используется odr, если применяя
преобразование lvalue в rvalue (4.1) в x дает постоянное выражение (5.19), которая не вызывает никакой нетривиальной
функции и, если x является объектом, ex является элементом множества потенциальных результатов выражения e, где
либо преобразование lvalue в rvalue (4.1) применяется к e, или e является выражением отброшенного значения
Обратите внимание, что Бен Фойгт сделал несколько полезных комментариев, которые немного прояснили этот вопрос. Так что рабочее предположение здесь таково, что Икс было бы:
y
а также е было бы(другое выражение, для которого определено e, рассматривается в пункте 2 раздела 3.2.):
(b ? y : x).n
y
дает константное выражение и преобразование lvalue-в-значение применяется к выражению е.
поскольку f
дает лямбду, которая захватывает f
локальные переменные по ссылке x
больше не действителен после звонка f
сделано с x
это автоматическая переменная внутри f
, поскольку y
это постоянное выражение это действует так, как будто y.n
не был доступен, и поэтому у нас нет той же проблемы жизни.
Ваш пример включен в N3939 раздел 4.1
[Conv.lval] и прямо перед этим примером написано:
Когда преобразование lvalue в rvalue применяется к выражению e, и либо
и включает в себя следующую маркировку, к которой относится исследование:
оценка результатов e в оценке члена ex из набора потенциальных результатов e, и
ex называет переменную x, которая не используется odr бывший (3.2),
затем:
значение, содержащееся в ссылочном объекте, не доступно
Это было применено к проекту стандарта C ++ 14 из-за Дефект 1773 .