Передача объекта в качестве аргумента функции по умолчанию по ссылке
Подскажите, пожалуйста, возможно ли реализовать следующий функционал:
У меня есть функция, которая рекурсивно вызывает сама себя и передает себе в качестве параметра вектор, который затем заполняется в теле функции, при этом при первом вызове функции данный параметр не указывается и берется по умолчанию:
void func(int level, std::vector<int> vec = { 0 }) {
if (level < 0)
return;
vec.push_back(level);
func(level - 1, vec);
}
Я не хотел бы каждый раз создавать новый вектор - это затраты памяти и времени (что более критично), поэтому хотел бы передавать вектор по ссылке:
void func(int level, std::vector<int>& vec = { 0 }) {
...
}
Чтобы это работало, вектор надо делать константным, что меня не устраивает, так как для изменения вектора опять надо делать копирование:
void func(int level, const std::vector<int>& vec = { 0 }) {
if (level < 0)
return;
std::vector<int> vec2(vec);
vec2.push_back(level);
func(level - 1, vec2);
}
Конечно, всегда остаётся возможность явно указывать вектор перед первым вызовом функции:
std::vector<int> vec = { 0 };
func(10, vec);
но так бы делать не хотелось, потому что данный вектор нужен исключительно внутри рекурсивной функции.
Подскажите, можно ли вообще реализовать этот замысел - при первом вызове никакой вектор не указывается, а берется из параметра по умолчанию, а во всех следующих вызовов используется старый вектор без каких-то дополнительных копирований и пересозданий.
P.S.
И не хотелось бы извратов в лоб по типу:
void func(int level, std::vector<int>* vec = new std::vector<int>({ 0 })) {
if (level < 0)
return;
vec->push_back(level);
func(level - 1, vec);
}
Хотя это, конечно, один из выходов, но как-то по ссылкам работать с объектами приятнее.
Ответы (2 шт):
Вы хотите создавать объект один раз, и при каждом рекурсивном вызове функции работать именно с этим объектом. Так создайте просто статический объект внутри функции(он и создастся только при первом вызове:
void func(int level) {
static std::vector<int> vec{ 0 };
if (level < 0)
return;
vec.push_back(level);
func(level - 1);
}
Но, как верно заметил Andrej Levkovitch, зачем вам этот вектор? Вы не хотите его указывать перед вызовом и не возвращаете из функции. Какую роль он выполняет? Тут или вы сами не ясно объяснили что вам нужно, или другая причина недопонимания...
Используйте rvalue ссылку, указав &&. Для этого при рекурсивном вызове придётся добавить std::move:
#include <vector>
void func(int level, std::vector<int>&& vec = {0}) {
if (level < 0)
return;
vec.push_back(level);
func(level - 1, std::move(vec));
}
int main() {
func(10);
}