Почему экземпляры std :: function имеют конструктор по умолчанию?
Это, вероятно, философский вопрос, но я столкнулся со следующей проблемой:
Если вы определите std :: function и не инициализируете ее правильно, ваше приложение будет аварийно завершено, например:
typedef std::function<void(void)> MyFunctionType;
MyFunctionType myFunction;
myFunction();
Если функция передается в качестве аргумента, вот так:
void DoSomething (MyFunctionType myFunction)
{
myFunction();
}
Тогда, конечно, это также вылетает. Это означает, что я вынужден добавить проверочный код следующим образом:
void DoSomething (MyFunctionType myFunction)
{
if (!myFunction) return;
myFunction();
}
Требование этих проверок возвращает меня назад к старым дням Си, где вам также пришлось явно проверить все аргументы указателя:
void DoSomething (Car *car, Person *person)
{
if (!car) return; // In real applications, this would be an assert of course
if (!person) return; // In real applications, this would be an assert of course
...
}
К счастью, мы можем использовать ссылки в C ++, что не позволяет мне писать эти проверки (при условии, что вызывающая сторона не передала содержимое nullptr в функцию:
void DoSomething (Car &car, Person &person)
{
// I can assume that car and person are valid
}
Итак, почему экземпляры std :: function имеют конструктор по умолчанию? Без конструктора по умолчанию вам не пришлось бы добавлять проверки, как и для других нормальных аргументов функции. И в тех «редких» случаях, когда вы хотите передать «необязательную» функцию std ::, вы все равно можете передать указатель на нее (или использовать boost :: необязательный).