2011-11-11 12 views
14

Esto compila perfectamente bien con la corriente MSVC compilador:sin inicializar const

struct Foo 
{ 
} const foo; 

Sin embargo, falla al compilar con la g corriente ++ compilador:

error: uninitialized const 'foo' [-fpermissive] 
note: 'const struct Foo' has no user-provided default constructor 

Si proporciono un constructor por defecto mismo, se obras:

struct Foo 
{ 
    Foo() {} 
} const foo; 

¿Es este otro caso de MSVC demasiado permisivo, o es g ++ demasiado estricto aquí?

+0

Gran pregunta Sr. Overflow. –

+0

Duplicados: http://stackoverflow.com/questions/5335836/why-a-const-object-of-an-empty-class-cant-be-created http://stackoverflow.com/questions/7411515/why- does-c-require-a-user-provided-default-constructor-to-default-build-a entre otros. – GManNickG

+0

No puedo reproducir esto en GCC 4.6.1, con cualquier opción de dialecto. Solo funciona si instalo una variable miembro (como 'int a;'), y el error es mucho más preciso: ''const struct Foo 'no tiene un constructor predeterminado proporcionado por el usuario y el constructor implícitamente definido no inicializa' int Foo :: a'' –

Respuesta

13

El C++ 03 estándar:

8,5 [dcl.init] párrafo 9

Si no se especifica el inicializador para un objeto, y el objeto es de (posiblemente cv -cualificado) tipo de clase no POD (o matriz de la misma), el objeto se inicializará por defecto; si el objeto es de tipo const-qualified, el tipo de clase subyacente tendrá un constructor predeterminado declarado por el usuario.

De lo anterior, el error en gcc parece ser perfectamente válido.

+7

+1 para Mr I'm-a-Hash-Table-of-the-Standard :-) –

1

No sé la redacción exacta de la norma, pero el error en g ++ parece bastante más sensato que la opción de no decir nada. Considere esto:

struct X { 
    int value; 
}; 
const X constant; // constant.value is undefined 

No en el caso de un usuario proporcionado constructor por defecto (incluso si no hace nada) el compilador llamará a ese constructor y el objeto será inicializado (por cualquier definición de inicializado se han implementado en su constructor).

3

[2003: 8.5/9]:Si no se especifica el inicializador para un objeto, y el objeto es de (posiblemente cv-cualificada)-POD no tipo de clase (o del mismo array ), el objeto será default-inicializado ; si el objeto es de tipo const-qualified, el tipo de clase subyacente tendrá un constructor predeterminado declarado por el usuario . De lo contrario, si no hay un inicializador especificado para un objeto no estático, el objeto y sus subobjetos, si alguno, tienen un valor inicial indeterminado; si el objeto o cualquiera de sus subobjetos son de tipo const-calificado, el programa está mal formado.

Y:

[n3290: 8.5/11]:Si no se especifica un inicializador para un objeto, el objeto es inicializado por defecto-; si no se realizó una inicialización , un objeto con duración de almacenamiento automática o dinámica tiene valor indeterminado. [Nota: Los objetos con almacenamiento estático o de subprocesos tienen una inicialización cero, consulte 3.6.2._ -end Note_]

[n3290: 8.5/6]: Para default-inicializar un objeto de tipo T significa:

  • si T es un tipo de clase (posiblemente cv-cualificada) (cláusula 9), el constructor predeterminado para T se llama (y la inicialización está mal formada si T no tiene un constructor por defecto accesible);
  • si T es un tipo de matriz, cada elemento se inicializa por defecto;
  • de lo contrario, no se realiza ninguna inicialización.

Si un programa llama a la inicialización por defecto de un objeto de una constante cualificado tipo T, T serán del tipo de clase con un constructor por defecto proporcionado por el usuario.

Por lo tanto, MSVC es más permisivo aquí que el mandato de ambos estándares.

Cuestiones relacionadas