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?

OVERLAPPEDes 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.mainC99 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
Personque 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).Persontiene 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 Xno 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 tipoTy 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.xes cero, por lo que podríamos esperar quefooesté optimizado en unoprintf.fooestá optimizado para imprimirx == 0únicamente.Para la versión C ++,
Y esta es la salida del código ensamblado optimizado.
Podemos ver que
a_pointrealmente 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 addrinfoostruct sockaddr_in, por lo que le quedan asignaciones separadas de las declaraciones.