plusplus plus pagina oficial library guidelines for c++ c++11 language-lawyer

plus - c++ website



¿Por qué no puedes omitir el tamaño de la matriz en un nuevo inicializador? (3)

Como Jonathan Wakely ya señaló en los comentarios, este es de hecho un tema cerrado. La resolución "debe manejarse en Evolution Work Group" esencialmente significa que WG21 piensa que no es una mala idea en sí misma, pero al mismo tiempo no la consideran un defecto en la norma actual. Lo que tiene sentido: no hay ninguna pista que funcione, es solo por analogía.

Esto está permitido:

int a[]{1, 2, 3};

Pero no esto:

auto a = new int[]{1, 2, 3};

Tienes que especificar los límites. ¿Por qué?

EDITAR: La sintaxis adecuada (que no se compila) es:

auto a = new (int[]){1, 2, 3};

Esto da el mensaje de error real, que es:

error: invalid use of array with unspecified bounds


Creo que se debe a que el compilador lee los archivos en el método en serie, nunca retrocede (es por eso que debe usar declaraciones hacia adelante, por ejemplo, y no solo esperar a que la función se declare más adelante). No estoy seguro de que sea la razón oficial, pero tiene sentido para mí.

Esta es mi explicación:

La línea int Array[]={1,2,3}; Se puede procesar de manera serial como esta:

iniciar matriz: ponga 1 en el primer lugar, ponga 2 en la segunda, ponga tres en la tercera, final de la matriz, por lo tanto: el tamaño de la matriz es de 3 enteros, así que mueva el marco de la pila por este tamaño.

Pero la siguiente línea: int *p=new int[]{1,2,3}; Debería haber comenzado con la asignación de memoria, además de colocar elementos en la memoria y detectar el tamaño. ¿Cómo se puede hacer de forma serial?

Para permitir algo como esto, debe romper el principio de serialidad, comenzar el procesamiento desde el final y luego volver a llamar al tamaño de asignación apropiado.

EDITAR:

En respuesta al primer comentario.

Hice alguna prueba, en el siguiente código:

class A{ public: A(){ err2 error; cout<<sizeof(A)<<endl; } err1 error; };

Parece que el compilador deja las funciones en línea para compilar como si fueran después de la clase.

La evidencia es que, independientemente del orden, los errores de los miembros se detectan antes que los errores de la función. Por lo tanto, en la clase de muestra, err1 error err2 error antes del err2 error , aunque el orden cronológico es el opuesto.

Por lo tanto, supongo que las clases son excepcionales, de lo contrario las funciones en clase eran muy limitadas en el uso de la clase en sí.

EDIT2:

int Array[]={sizeof(Array)}; da error, la única razón es que el tamaño de la matriz se da después del cierre de la matriz. es más similar al problema en la pregunta que int Array[]={1,2};


La respuesta de MSalters explica por qué esto no se ha modificado en las versiones recientes del estándar. Aquí responderé a la pregunta complementaria, "¿en qué parte del estándar C ++ 11 está prohibido?"

Con respecto a new (int[]){1, 2, 3}

Primero, debemos tener en cuenta que int[] es un tipo incompleto.

... una matriz de tamaño desconocido ... es un tipo de objeto definido de forma incompleta. - [tipos de base] §3.9 ¶5

Finalmente, observamos que el new operador no permite que el tipo especificado esté incompleto:

Este tipo será un tipo de objeto completo ... - [expr.new] §5.3.4 ¶1

No hay nada en el estándar para hacer una excepción para este caso cuando se usa la sintaxis de lista de inicio con braces.

Con respecto a new int[]{1, 2, 3}

int[] en este caso, se analiza utilizando la producción new-type-id , que utiliza la producción noptr-new-declarator para analizar los corchetes:

noptr-nuevo-declarador:
[ expresión ] atributo-especificador-seq opt
noptr-new-declarator [ expresión-constante ] atributo-especificador-seq opt

Tenga en cuenta que la expresión no está marcada como opcional, por lo tanto, esta sintaxis simplemente no se puede analizar.