Considerar:
struct Person
{
int height;
int weight;
int age;
};
int main()
{
Person p { .age = 18 };
}
El código anterior es legal en C99, pero no es legal en C ++ 11.
Cual fue el c ++ 11 ¿Cuál es el fundamento del comité estándar para excluir el soporte para una característica tan útil?
OVERLAPPED
es un ejemplo. Ser capaz de escribir={.Offset=12345};
haría que el código fuera mucho más claro (y probablemente menos propenso a errores). Los enchufes BSD son un ejemplo similar.main
C99 no es legal. Debería leerstruct Person p = { .age = 18 };
Respuestas:
C ++ tiene constructores. Si tiene sentido inicializar solo un miembro, entonces eso se puede expresar en el programa implementando un constructor apropiado. Este es el tipo de abstracción que promueve C ++.
Por otro lado, la función de inicializadores designados se trata más de exponer y facilitar el acceso de los miembros directamente en el código del cliente. Esto lleva a cosas como tener una persona de 18 años (¿años?) Pero con una altura y un peso de cero.
En otras palabras, los inicializadores designados admiten un estilo de programación en el que se exponen los componentes internos y el cliente tiene flexibilidad para decidir cómo desea utilizar el tipo.
C ++ está más interesado en poner la flexibilidad del lado del diseñador de un tipo, por lo que los diseñadores pueden facilitar el uso correcto de un tipo y dificultar el uso incorrecto. Poner al diseñador en control de cómo se puede inicializar un tipo es parte de esto: el diseñador determina los constructores, los inicializadores en clase, etc.
fuente
Person
que su autor quisiera proporcionar la mayor flexibilidad posible para que los usuarios establezcan e inicialicen los miembros? El usuario también puede escribirPerson p = { 0, 0, 18 };
(y por buenas razones).Person
tiene un diseño muy C, por lo que las funciones C pueden tener sentido. Sin embargo, C ++ probablemente permite un mejor diseño que también evita la necesidad de inicializadores designados. - En mi opinión, eliminar la restricción de los inicializadores de clase para los agregados está mucho más en línea con el espíritu de C ++ que los inicializadores designados.El 15 de julio de 2017 P0329R4 fue aceptado en elc ++ 20estándar: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf
Esto brinda soporte limitado parac99Inicializadores designados. Esta limitación se describe como sigue en C.1.7 [diff.decl] .4, dado:
Las siguientes inicializaciones designadas, que son válidas en C, están restringidas en C ++:
struct A a = { .y = 1, .x = 2 }
no es válido en C ++ porque los designadores deben aparecer en el orden de declaración de los miembros de datosint arr[3] = { [1] = 5 }
no es válido en C ++ porque la inicialización designada por matriz no es compatiblestruct B b = {.a.x = 0}
no es válido en C ++ porque los designadores no se pueden anidarstruct A c = {.x = 1, 2}
no es válido en C ++ porque todos o ninguno de los miembros de datos deben ser inicializados por designadorespor c ++ 17y Boost anterior en realidad tiene soporte para Intializadores designados y ha habido numerosas propuestas para agregar soporte a lac ++estándar, por ejemplo: n4172 y la propuesta de Daryle Walker para agregar una designación a los inicializadores . Las propuestas citan la implementación dec99Inicializadores designados en Visual C ++, gcc y Clang que afirman:
Pero el comité estándar rechaza repetidamente tales propuestas , afirmando:
Los comentarios de Ben Voigt me han ayudado a ver los problemas insuperables con este enfoque; dado:
¿En qué orden se llamarían estas funciones en c99:
struct X foo = {.a = (char)f(), .b = g(), .c = h()}
? Sorprendentemente, enc99:(Visual C ++, gcc y Clang parecen tener un comportamiento acordado, ya que todos realizarán las llamadas en este orden :)
h()
f()
g()
Pero la naturaleza indeterminada del estándar significa que si estas funciones tuvieran alguna interacción, el estado del programa resultante también sería indeterminado, y el compilador no le advertiría : ¿Hay alguna manera de recibir una advertencia sobre los inicializadores designados que se comportan mal?c ++ no tienen requisitos estrictos de inicialización de listas 11.6.4 [dcl.init.list] 4:
Entonces c ++ El soporte habría requerido que esto se ejecutara en el orden:
f()
g()
h()
Rompiendo la compatibilidad con anteriores c99implementaciones.
Como se discutió anteriormente, este problema ha sido eludido por las limitaciones en Inicializadores Designados aceptados enc ++ 20. Proporcionan un comportamiento estandarizado, garantizando el orden de ejecución de los Inicializadores Designados.
fuente
struct X { int c; char a; float b; }; X x = { .a = f(), .b = g(), .c = h() };
la llamada ah()
se realiza antes def()
og()
. Si la definición destruct X
no está cerca, esto será muy sorprendente. Recuerde que las expresiones de inicializador no tienen por qué estar libres de efectos secundarios.Un poco de piratería, así que solo comparte por diversión.
Y utilícelo como:
que se expande a:
fuente
$
de tipoT
y usted asigna sus miembros directamente antes de devolverla. Hábil. Me pregunto si hay algún problema de rendimiento con él.Los inicializadores designados se incluyen actualmente en el cuerpo de trabajo de C ++ 20: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf ¡ así que finalmente podríamos verlos!
fuente
&
operador devolvería la dirección que tendrá el objeto durante su vida útil).Dos características principales de C99 de las que C ++ 11 carece menciona "Inicializadores designados y C ++".
Creo que el 'inicializador designado' relacionado con la optimización potencial. Aquí utilizo “gcc / g ++” 5.1 como ejemplo.
Sabíamos que en el momento de la compilación
a_point.x
es cero, por lo que podríamos esperar quefoo
esté optimizado en unoprintf
.foo
está optimizado para imprimirx == 0
únicamente.Para la versión C ++,
Y esta es la salida del código ensamblado optimizado.
Podemos ver que
a_point
realmente no es un valor constante de tiempo de compilación.fuente
constexpr point(int _x,int _y):x(_x),y(_y){}
. El optimizador de clang ++ parece eliminar la comparación en su código también. Entonces, esto es solo un problema de QoI.struct addrinfo
ostruct sockaddr_in
, por lo que le quedan asignaciones separadas de las declaraciones.