Question

There are four specific cases , where you must specify default initializer list. Fully discussed here

In short, if you have

Initializer list Required

  1. non-static const data members
  2. data member of reference type
  3. provide params to data members which are objects of other class
  4. provide base class ctor parameters from derived class.

The one drawback to default argument seems to be that the default arguments must be the trailing parameters in the function prototype parameter list. For example:

drawbacks(???) to default arguments

void f(int, int = 2, int = 3);     // trailing defaults
void g(int = 1, int = 2, int c);   // error
void h(int, int = 3, int);         // error

My question is, if my code does not fall in between the 4 required cases for initializer list and always requires all parameters to have default values, i.e. does not lead to the drawbacks to default arguments , which one should I choose and why? What is the best practice?

an example being

// option -1: for the default argument list
// my_array.h
my_array(int a_number_of_elements = 0, int default_val = 0);

//option-2 : default initalizer list
// my_array.h
my_array(int a_number_of_elements, int default_val);
//my_array.cpp
my_array:: my_array(int a_number_of_elements, int default_val)
                   : my_num_elements(a_num_elements), my_default_value(default_val)

Thanks for looking.

Was it helpful?

Solution

You are dealing with two completely different things here: constructor initializer lists vs default function arguments.

You got most of what you said correctly, but contrary to what you might believe, default constructor arguments do not imply the construction of data members using these values, unless you explicitly state so. Hence, one technique is not a replacement for the other, just separate complementary things.

For example:

// my_array.h
my_array(int a_number_of_elements = 1, int default_val = 0);
//my_array.cpp
my_array:: my_array(int a_number_of_elements, int default_val)
                   : my_num_elements(a_num_elements), my_default_value(default_val)

will [be expected to] initialize an array with one element of value zero.

If you do not explicitly call the constructors of the data members, then their default constructors, if available, will be called, so the following two are equivalent.

//implicitly default constructing members
my_array:: my_array()
{}
//explicitly default constructing members
my_array:: my_array() :
    my_num_elements(), my_default_value()
{}

Regarding the two above, it is always a good idea to leave things explicit for better legibility. As often said, a given code is usually written once, but read many times.

OTHER TIPS

You have a couple misconceptions here:

  1. You are referring to "Constructor Initializer Lists" as initializer_lists
  2. You seem to think that defaulted arguments can only be used separately from "Constructor Initialization Lists"

Lets talk about some principles here:

  • You'll always want to use a "Constructor Initializer List" for all your variables, not just those of the 4 types you mention. "Constructor Initializer Lists" value initialize, rather than default initializing and requiring you to assign to them in the constructor body
  • Where possible you'll always want to have a default constructor, as this is required for using your object in standard containers
  • Defaulting arguments is a great way to prevent code duplication for both a user defined constructor and a user defined default constructor

So using these principles I can say that the answer to your question is yes, that the ideal situation would be to to use both "Constructor Initializer Lists" and default arguments. Resulting in a constructor that looks something like:

my_array(int a_number_of_elements = 0, int default_val = 0) :
    my_num_elements(a_number_of_elements),
    my_default_value(default_val) {}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top