c++ - Comprender el ejemplo de conversión de valor a valor
language-lawyer c++14 (1)
Me cuesta entender cómo este código (un ejemplo del borrador del estándar C ++ 14
[conv.lval]
) invoca un comportamiento indefinido para
g(false)
.
¿Por qué
constexpr
hace que el programa sea válido?
Además, ¿qué significa "no accede a
yn
"?
En ambas llamadas a
g()
estamos devolviendo el miembro de datos
n
, entonces ¿por qué la última línea dice que no accede a él?
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
Esto se debe a que
yn
no se usa odr y, por lo tanto, no requiere acceso a
yn
las reglas para el uso de odr están cubiertas en
3.2
y dice:
Una variable x cuyo nombre aparece como una expresión potencialmente evaluada, ex, se usa odr, a menos que la aplicación de la conversión lvalue-to-rvalue (4.1) a x produzca una expresión constante (5.19) que no invoque ninguna función no trivial y, si x es un objeto, ex es un elemento del conjunto de resultados potenciales de una expresión e, donde la conversión lvalue-to-rvalue (4.1) se aplica a e , oe es una expresión de valor descartado
Tenga en cuenta que Ben Voigt hizo algunos comentarios útiles que aclararon esto un poco. Entonces, la suposición de trabajo aquí es que x sería:
y
y e sería ( la expresión diferente para la que se define e se trata en el párrafo 2 de la sección 3.2 ):
(b ? y : x).n
y
produce una expresión constante y la conversión de valor a valor se aplica a la expresión
e
.
Dado que
f
produce una lambda que captura las variables locales de
f
por referencia
x
ya no es válida una vez que se realiza la llamada a
f
ya que
x
es una variable automática dentro de
f
.
Dado que
y
es una
expresión constante
, actúa como si no se accediera a
yn
y, por lo tanto, no tenemos el mismo problema de por vida.
Su ejemplo se incluye en
N3939
sección
4.1
[conv.lval]
y justo antes de ese ejemplo dice:
Cuando se aplica una conversión lvalue-to-rvalue a una expresión e, y
e incluye la siguiente viñeta a la que pertenece el examen:
la evaluación de e da como resultado la evaluación de un miembro ex del conjunto de resultados potenciales de e, y ex nombra una variable x que no es odr-utilizada por ex (3.2),
entonces:
no se accede al valor contenido en el objeto referenciado
Esto se aplicó al borrador del estándar C ++ 14 debido al informe de defectos 1773 .