Ya hay excelentes respuestas sobre las ventajas de usar la inicialización de la lista, sin embargo, mi regla general personal es NO usar llaves siempre que sea posible, sino que dependerá del significado conceptual:
- Si el objeto que estoy creando conceptualmente contiene los valores que paso en el constructor (por ejemplo, contenedores, estructuras de POD, atómicos, punteros inteligentes, etc.), entonces estoy usando llaves.
- Si el constructor se parece a una llamada de función normal (realiza algunas operaciones más o menos complejas que están parametrizadas por los argumentos), entonces estoy usando la sintaxis de llamada de función normal.
- Para la inicialización predeterminada, siempre uso llaves.
Por un lado, de esa manera siempre estoy seguro de que el objeto se inicializa independientemente de si es, por ejemplo, una clase "real" con un constructor predeterminado que se llamaría de todos modos o un tipo incorporado / POD. En segundo lugar, es, en la mayoría de los casos, coherente con la primera regla, ya que un objeto inicializado predeterminado a menudo representa un objeto "vacío".
En mi experiencia, este conjunto de reglas se puede aplicar de manera mucho más consistente que el uso de llaves por defecto, pero tener que recordar explícitamente todas las excepciones cuando no se pueden usar o tienen un significado diferente que la sintaxis de llamada de función "normal" con paréntesis (Llama a una sobrecarga diferente).
Por ejemplo, encaja perfectamente con tipos de biblioteca estándar como std::vector
:
vector<int> a{10,20}; //Curly braces -> fills the vector with the arguments
vector<int> b(10,20); //Parentheses -> uses arguments to parametrize some functionality,
vector<int> c(it1,it2); //like filling the vector with 10 integers or copying a range.
vector<int> d{}; //empty braces -> default constructs vector, which is equivalent
//to a vector that is filled with zero elements
auto
?