recorrer que objetos lista inicializar ejemplo arreglo array c++ initialization stdvector undefined-behavior

objetos - que es un arreglo en c++



Vector de objeto que contiene valor no inicializado (2)

Entonces, teniendo en cuenta el siguiente comentario del PO:

vector vec (5); no es UB (¿verdad?) y tendemos a pensar que (5) y (5, S ()) deberían hacer lo mismo. Pude ver este error por accidente con bastante facilidad.

La pregunta se reduce a si:

vector<S> vec(5);

Está bien definido, entonces ¿por qué es?

std::vector<S> vec(5, S());

comportamiento indefinido?

Si vamos a la sección cppreference de std :: vector :: vector , podemos ver en el primer caso ( desde C ++ 11 ) ( énfasis mío ):

Construye el contenedor con el conteo de incidencias de T. insertadas por defecto. No se realizan copias .

mientras que en el segundo caso:

Construye el contenedor con el recuento de copias de elementos con valor de valor.

El primer caso construirá los elementos por defecto y no se harán copias, mientras que en el segundo caso se realizarán copias y, por lo tanto, terminaremos copiando x en cada elemento. Como el constructor predeterminado de S no inicializa x , tendrá un valor indeterminado y, por lo tanto, tenemos un comportamiento indefinido, ya que producir un valor indeterminado invoca un comportamiento no definido.

Como C ++ 14 sección 8.5 párrafo 12 dice:

Si una evaluación produce un valor indeterminado, el comportamiento no está definido, excepto en los siguientes casos

con algunas excepciones en el caso de char sin signo que no se aplica en este caso.

Sabemos que x tiene un valor indeterminado del mismo párrafo que dice:

Cuando se obtiene almacenamiento para un objeto con una duración de almacenamiento automática o dinámica, el objeto tiene un valor indeterminado, y si no se realiza la inicialización para el objeto, ese objeto conserva un valor indeterminado hasta que ese valor sea reemplazado

¿Este código causa un comportamiento indefinido?

#include <vector> struct S { S() {} int x; }; int main() { std::vector<S> vec(5, S()); }

Como S() predetermina: inicializa un objeto automático, sus contenidos no se ponen a cero primero, por lo que x sería indeterminado. Luego, el objeto que contiene un valor indeterminado se copia a cada ubicación del vector.

Motivación: Podríamos esperar que esto se comporte de la misma manera que std::vector<S> vec(5); que no es UB (ya que C ++ 11), por lo que sería un error fácil de realizar por accidente.

Como se refiere Praetorian en los comentarios, antes de C ++ 11 std::vector<S> vec(5); era libre de realizar 5 inicializaciones predeterminadas o utilizar el constructor de copia para algunos o todos los elementos.


TL; DR Sí, esto es un comportamiento indefinido.

En su código, usted valora-inicializa un temporal:

std::vector<S> vec(5, S()); // ^^^

De §8.5 / 10:

Un objeto cuyo inicializador es un conjunto vacío de paréntesis, es decir, () , se inicializará en valor.

La definición de inicialización de valor es:

§8.5 / 8

Valorizar-inicializar un objeto de tipo T significa:

- si T es un tipo de clase (posiblemente cv calificado) (Cláusula 9) con ningún constructor predeterminado (12.1) o un constructor predeterminado proporcionado por el usuario o eliminado, entonces el objeto se inicializa por defecto;

- [..]

La inicialización del valor no incluye la inicialización cero en este caso porque S tiene un constructor predeterminado declarado por el usuario. Por lo tanto, está construido por defecto.

§8.5 / 7

Para inicializar por defecto un objeto de tipo T significa:

- Si T es un tipo de clase (posiblemente cv calificado) (Cláusula 9), se consideran constructores. Los constructores aplicables se enumeran (13.3.1.3) y el mejor para el inicializador () se elige a través de la resolución de sobrecarga (13.3). El constructor así seleccionado se llama, con una lista de argumentos vacía, para inicializar el objeto.

- Si T es un tipo de matriz, cada elemento se inicializa por defecto.

- De lo contrario, no se realiza ninguna inicialización.

Como el constructor predeterminado no inicializa explícitamente x , mantiene su valor de basura no inicializado. El constructor de copia predeterminado inicializa los otros elementos con estos valores que son UB.

§8.5 / 12

Si la evaluación produce un valor indeterminado, el comportamiento no está definido