#cpp #функции #ссылки #параметры
Как передать функции параметр по ссылке со значением по умолчанию? void func(int &i) void func2(set&s) и при этом иметь возможность вызывать эти функции без аргументов, чтобы переменной i присваивалось значение по умолчанию, а для s вызывался конструктор, чтобы использовать множество set в теле функции.
Ответы
Ответ 1
Если вы хотите использовать аргумент по умолчанию по ссылке, то этот аргумент должен быть не временным объектом и уже где-то быть определенным на момент вызова функции. Передача аргумента по неконстантной ссылке предполагает, что этот исходный аргумент будет в функции изменен. Вы не можете передавать по неконстантной ссылке временные объекты. Поэтому, исходя из условий, указанных в вашем вопросе, скорей всего у вас должны быть две перегруженные функции. Одна функция принимает аргумент по lvalue-ссылке с конкретно заданным объектом. Вторая функция оибл принимает временный объект по rvalue-сслке, оибо вместо него использует значение по умолчанию. Например, #includevoid func( int &i ) { ++i; std::cout << "Inside func( int & ) i = " << i << std::endl; } void func( int &&i = int() ) { ++i; std::cout << "Insde func( int && ) i = " << i << std::endl; } int main() { int i = 0; std::cout << "Before func( i ) i = " << i << std::endl; func( i ); std::cout << "After func( i ) i = " << i << std::endl; std::cout << std::endl; i = 0; std::cout << "Before func() i = " << i << std::endl; func(); std::cout << "After func() i = " << i << std::endl; return 0; } Вывод программы на консоль: Before func( i ) i = 0 Inside func( int & ) i = 1 After func( i ) i = 1 Before func() i = 0 Insde func( int && ) i = 1 After func() i = 0 В этой программе, когда в качестве аргумента передается lvalue, то используется первая функция void func( int &i ) { ++i; std::cout << "Inside func( int & ) i = " << i << std::endl; } и она меняет в своем теле исходный аргумент. Когда же аргумент не указывается, или когда указывается rvalue, то есть некоторый временный объект, как, например, func(); // используется аргумент по умолчанию int(), который равен 0 или func( 10 ); // используется временный объект - целочисленный литерал - 10 то используется вторая функция void func( int &&i = int() ) { ++i; std::cout << "Insde func( int && ) i = " << i << std::endl; } Если же вы не собираетесь изменять исходный аргумент, то достаточно объявить одну функцию с параметром в виду константной ссылки. Например, void func( const int &i = int() ); Ответ 2
Ну, первый случай несложен - если вы хотите иметь возможность использовать значение по умолчанию, то используйте const int& - void f(const int& i = 5) { cout << i << endl; } Без const, как вы понимаете, вам не удастся передать значение - ведь что тогда вы собираетесь менять, передавая число? :) А вот так - можно: int j = 5; void f(int& i = j) { cout << i << endl; } int main(int argc, const char * argv[]) { int q = 4; f(); f(q); } Соответственно, то же и с set& - как вы себе представляете для s вызывался конструктор, чтобы использовать множество set в теле функции Т.е. вы хотите создавать новый set ? Тогда где он должен быть создан? Как локальная переменная, как глобальная, как переменная в вызывающей функции? Так что по умолчанию для ссылки надо указывать имеющийся объект. Другое просто не имеет никакого смысла. В конце концов, ссылка - это просто адрес, ждя которого гарантируется наличие корректного объекта. "По-моему, так" (с) Пух Ответ 3
Если вам нужна именно неконстантная ссылка, то сделать в такой ситуации можно что-то вроде void func2(set&s = some_function()) где some_function это set &some_function() { ... } некая функция, которая отвечает за создание этих экземпляров std::set в некоем хранилище. Отдельно придется подумать об обеспечении некоей политики их последующего уничтожения, когда они станут ненужными. Как это будет делаться - вопрос отдельный и элегантных решений тут навскидку не видно. Оптимальное решение может зависеть от конкретной специфики вашей задачи, но сама идея неявного создания (потенциально долгоживущих) объектов через параметр по-умолчанию - сомнительна.
Комментариев нет:
Отправить комментарий