Аргумент С++ по умолчанию и список инициализаторов

Есть четыре конкретных случая, когда вы должны указать список инициализаторов по умолчанию. Подробно обсуждается здесь

Короче говоря, если у вас есть

Обязательный список инициализаторов

  1. нестатические константные элементы данных
  2. элемент данных ссылочного типа
  3. предоставить параметры членам данных, которые являются объектами другого класса
  4. предоставить параметры ctor базового класса из производного класса.

Единственным недостатком аргумента по умолчанию является то, что аргументы по умолчанию должны быть завершающими параметрами в списке параметров прототипа функции. Например:

недостатки(???) аргументов по умолчанию

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

Мой вопрос в том, что если мой код не попадает между 4 обязательными случаями для списка инициализаторов и всегда требует, чтобы все параметры имели значения по умолчанию, т.е. не приводит к недостаткам аргументов по умолчанию, какой из них я должен выбрать и почему? Какова наилучшая практика?

пример

// 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)

Спасибо, что посмотрели.


person thassan    schedule 13.09.2013    source источник
comment
В пункте 1 следует указать нестатические элементы данных const.   -  person john    schedule 14.09.2013
comment
Аргументы по умолчанию для функций и списки инициализаторов конструктора - разные и независимые вещи...   -  person lapk    schedule 14.09.2013
comment
Я думаю, что интерфейс std::vector является довольно хорошим примером разумного контейнера, похожего на массив...   -  person Kerrek SB    schedule 14.09.2013
comment
@john отредактировал сообщение. Блин, тут одни пуритане :)   -  person thassan    schedule 14.09.2013


Ответы (2)


Здесь вы имеете дело с двумя совершенно разными вещами: списки инициализаторов конструктора и аргументы функции по умолчанию.

Вы правильно поняли большую часть того, что сказали, но вопреки тому, что вы могли бы подумать, аргументы конструктора по умолчанию не подразумевают создание элементов данных с использованием этих значений, если только вы не указали это явно. Следовательно, одна техника не является заменой другой, а лишь отдельными взаимодополняющими вещами.

Например:

// 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)

[ожидается, что] инициализирует массив одним элементом с нулевым значением.

Если вы явно не вызываете конструкторы элементов данных, то будут вызываться их конструкторы по умолчанию, если они доступны, поэтому следующие два эквивалентны.

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

Что касается двух вышеизложенных, всегда полезно оставлять вещи явными для лучшей разборчивости. Как часто говорят, данный код обычно пишется один раз, но читается много раз.

person brunocodutra    schedule 13.09.2013

У вас есть пара неправильных представлений:

  1. Вы ссылаетесь на "Списки инициализаторов конструктора" как на initializer_lists
  2. Кажется, вы думаете, что аргументы по умолчанию можно использовать только отдельно от «списков инициализации конструктора».

Давайте поговорим о некоторых принципах здесь:

  • Вы всегда будете использовать "Список инициализаторов конструктора" для всех ваших переменных, а не только для тех 4 типов, которые вы упомянули. Значение «Списки инициализаторов конструктора» инициализируется, а не инициализируется по умолчанию и требует, чтобы вы назначали их в теле конструктора.
  • Там, где это возможно, вы всегда захотите иметь конструктор по умолчанию, так как это необходимо для использования вашего объекта в стандартных контейнерах.
  • Аргументы по умолчанию — отличный способ предотвратить дублирование кода как для пользовательского конструктора, так и для пользовательского конструктора по умолчанию.

Таким образом, используя эти принципы, я могу сказать, что ответ на ваш вопрос положительный, что идеальной ситуацией было бы использование оба "списков инициализаторов конструктора" и аргументов по умолчанию. Результат в конструкторе, который выглядит примерно так:

my_array(int a_number_of_elements = 0, int default_val = 0) :
    my_num_elements(a_number_of_elements),
    my_default_value(default_val) {}
person Jonathan Mee    schedule 13.06.2016