Понимание примера преобразования lvalue в rvalue
Мне трудно понять, как этот код (пример из проекта стандарта 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
1 ответ
Это потому что y.n
не используется odr и поэтому не требует доступа к y.n
правила использования odr описаны в 3.2
и говорит:
Переменная x, имя которой появляется в качестве потенциально оцениваемого выражения ex, используется odr, если только при применении преобразования lvalue-to-rvalue (4.1) в x не получается константное выражение (5.19), которое не вызывает никаких нетривиальных функций и, если x является объектом, ex является элементом набора потенциальных результатов выражения e, где к e применяется либо преобразование lvalue-в-значение (4.1), либо e является выражением отброшенного значения
Обратите внимание, что Бен Фойгт сделал несколько полезных комментариев, которые немного прояснили этот вопрос. Таким образом, рабочее предположение здесь, что х будет:
y
и e будет (другое выражение, для которого определено e, рассматривается в пункте 2 раздела 3.2):
(b ? y : x).n
y
дает константное выражение и преобразование lvalue в rvalue применяется к выражению e.
поскольку f
дает лямбду, которая захватывает f
локальные переменные по ссылке x
больше не действителен после звонка f
сделано с x
это автоматическая переменная внутри f
, поскольку y
является постоянным выражением, оно действует так, как будто y.n
не был доступен, и поэтому у нас нет той же проблемы жизни.
Ваш пример включен в раздел N3939 4.1
[conv.lval] и прямо перед этим примером написано:
Когда преобразование lvalue в rvalue применяется к выражению e, и либо
и включает в себя следующую маркировку, к которой относится исследование:
оценка e приводит к оценке члена ex из набора потенциальных результатов e, и ex называет переменную x, которая не используется odr в ex (3.2),
затем:
значение, содержащееся в ссылочном объекте, не доступно
Это было применено к проекту стандарта C++14 из-за сообщения об ошибке 1773.