2008-10-02 23 views
13

Observé un código de un colega hoy que inicializó las variables de clase en la inicialización. Sin embargo, estaba causando una advertencia, dice él debido al orden en que se encuentran. Mi pregunta es ¿por qué es mejor hacer la inicialización de la variable donde está actualmente y no dentro de las llaves?Inicialización de la clase C++ que contiene la inicialización de variable de clase

DiagramScene::DiagramScene(int slideNo, QRectF screenRect, MainWindow* parent) 
    : QGraphicsScene(screenRect, parent), 
    myParent(parent), 
    slideUndoImageCurrentIndex(-1), 
    nextGroupID(0), 
    m_undoInProgress(false), 
    m_deleteItemOnNextUndo(0) 
    line(0), 
    path(0) 
{ 
    /* Setup default brush for background */ 
    scDetail->bgBrush.setStyle(Qt::SolidPattern); 
    scDetail->bgBrush.setColor(Qt::white); 
    setBackgroundBrush(scDetail->bgBrush); 

} 
+1

Sólo una observación terminológica general: se trata de variables miembro. Las variables miembro pertenecen a un objeto. Las variables de clase no existen en C++, mientras que sí lo hacen en p. Ruby, y sirven más o menos para el propósito de las variables miembro estáticas de C++. – xtofl

Respuesta

26
  • es más eficiente (en general). Todos los miembros de una clase se inicializan en el constructor, ya sea que los inicie explícitamente o no. Si no especifica un inicializador, se ejecuta el constructor predeterminado del miembro. Si asigna un valor en el cuerpo del constructor, se llama nuevamente al operador de asignación. Esto no se aplica a los valores escalares, como en su ejemplo, ya que los valores escalares no tienen constructores.
  • No puede asignar accidentalmente un valor dos veces en la lista de inicializadores.
  • El compilador puede verificar para asegurarse de que el orden en el que escribe los inicializadores coincide con el orden en que se definen los miembros en la clase. El estándar de C++ requiere que los miembros se inicialicen en el orden en que se declaran, independientemente del orden en que se escriban los iniciadores. Hacer que el compilador compruebe este orden garantiza que el programador sepa en qué orden se ejecutarán los iniciadores (de nuevo, esto es más importante para los miembros que no son POD que para los escalares).
  • Los tipos de referencia y los miembros const se deben inicializar en la lista de inicializadores, porque no se puede asignar a una referencia oa un miembro const.
2

Porque, en el cuerpo del constructor ("dentro de las llaves") las variables miembro ya están construidas por defecto. Esto puede tener algunas implicaciones de rendimiento, cuando tiene una variable miembro de un tipo que tiene una construcción no trivial, cuando la tiene construida por defecto y luego le asigna algún otro valor en el constructor, cuando puede tener una construcción personalizada directamente

Además, algunos tipos pueden no estar construidos por defecto (por ejemplo, referencias) y deben construirse en la lista de inicialización.

+0

Gracias, se agregó una nota sobre las referencias. +1 –

2

Si tiene las variables const, su valor no se puede ajustar a través de la asignación.

La inicialización también es un poco más eficiente cuando se asignan valores a objetos (no integrados o intrínsecos) ya que un objeto temporal no se crea como lo sería para una tarea.

Ver C++ FAQ-Lite para más detalles

4

Es mejor hacer la inicialización de los miembros de la lista de inicialización debido a que los miembros se inicializan entonces sólo una vez. Esto puede ser una gran diferencia en el rendimiento (e incluso el comportamiento) si los miembros son clases en sí mismos. Si los miembros son todos tipos de datos fundamentales no const, sin referencia, entonces la diferencia es usualmente insignificante.

NOTA: Hay momentos en los que se requieren listas de inicialización para tipos de datos fundamentales, específicamente si el tipo es constante o una referencia. Para estos tipos, los datos solo se pueden inicializar una vez y, por lo tanto, no se pueden inicializar en el cuerpo del constructor. Consulte this article para obtener más información.

Tenga en cuenta que el orden de inicialización de los miembros es el orden en que los miembros se declaran en la definición de clase, no el orden en que los miembros se declaran en la lista de inicialización. Si la advertencia puede solucionarse cambiando el orden de la lista de inicialización, le recomiendo encarecidamente que lo haga.

Es mi recomendación de que:

  • Se aprende a como las listas de inicialización.
  • Su compañero de trabajo comprende las reglas para el orden de inicialización de los miembros (y evita las advertencias).
3

Además de Greg Hewgill, excellent answer - las variables const deben configurarse en la lista de inicialización.

+0

Gracias, se agregó una nota sobre los miembros de const. +1 –

0

Otra adición a la respuesta de Greg: los miembros que son de tipos sin un constructor predeterminado deben inicializarse en la lista de inicialización.

0

La respuesta de Greg Hegwell contiene algunos consejos excelentes, pero no explica por qué el compilador está generando una advertencia.

Cuando el compilador procesa la lista de inicializadores de un constructor, los elementos se inicializan en el orden en que se declaran en la declaración de clase, no en el orden en que aparecen en la lista de inicializadores.

Algunos compiladores generan una advertencia si el orden en la lista de inicializadores es diferente del orden de la declaración (por lo que no se sorprenderá cuando los elementos no se inicialicen en el orden de la lista). No incluye su declaración de clase, pero esta es la causa probable de la advertencia que está viendo.

La razón de este comportamiento es que los miembros de una clase siempre deben inicializarse en el mismo orden: incluso cuando la clase tiene más de un constructor (que podría ordenar los miembros de manera diferente en sus listas de inicializadores).

Cuestiones relacionadas