2013-12-22 2 views
0

Поскольку рекурсия имеет дополнительные накладные расходы на то, что происходит нажатие и запись записей активации, можно ли это избежать, когда дело доходит до использования констант?Может ли рекурсивная функция знать о константе в функции, в которой она была сначала вызвана, не отправив ей константу в качестве параметра?

Например, если у меня есть функция

void foo(int x) { 
    int bar = x; 
    fooAux(root); 
} 

fooAux(Root * root) { 
    // Can I somehow do something with the variable bar here? 
    // {Insert recursive code} 
} 

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

+1

Возможно, это не самая важная проблема с производительностью, о которой нужно беспокоиться. – user2357112

+0

Как насчет добавления другого аргумента в 'fooAux()'? –

+0

@ H2CO3: Это работает, но это решение, которое OP специально пытается избежать. – user2357112

ответ

1

Вопрос не очень ясен, ссылаясь на «константу» в заголовке, но затем в примере кода с использованием переменной.

В любом случае ответ «да», рекурсивная вспомогательная функция может легко ссылаться на константу или переменную в нерекурсивной функции вызывающего абонента, если безопасность потоков не вызывает беспокойства.

Все, что вам нужно сделать, это объявить переменную static:

struct Whatever {}; 

void foo(int x) 
{ 
    static int bar; 

    struct Aux 
    { 
     static void foo(Whatever) 
     { 
      (void) bar; 
     } 
    }; 

    bar = x; 
    Aux::foo(Whatever()); 
} 

Является ли это хорошая идея? Нет, он пахнет преждевременной оптимизации. Прирост скорости, если таковой будет, будет незначительным, а стоимость обслуживания может быть высокой.

+0

Чтобы создать резервную копию, это не очень хорошая идея: как и преждевременная оптимизация, она пахнет не реентерабельными (что делает ее небезопасной, как вы упомянули, а также * безошибочной). –

1

Вы можете сделать это, используя глобальную переменную, например: g_bar. Однако это делает вашу функцию не реентеративной или элегантной.

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

0

Если вы правильно поняли, что вы задаете вопрос не о рекурсии, но и о области. Возможно, вы также можете жить с ответом на вопрос: Может ли функция получить доступ к переменной, которая не передается в качестве параметра (и не определена локально)

Ответ на этот вопрос «да». Существует несколько вариантов:

  • Функция может иметь доступ к глобальным переменным. Во многих случаях это анти-шаблон и не совсем то, что вы ищете.
  • Существует очень интересная концепция закрытия , которая очень близка к тому, что вы ищете. Он позволяет функции получить доступ к «environmentemnt», в котором может находиться ваша переменная bar.

Однако в C++ нет замыканий, и я не знаю какого-либо изящного способа имитации замыканий на C++. Также закрыты, где изобретаются по семантическим причинам (это дает программистам больше энергии), а не по соображениям производительности.

+1

«в C++ нет закрытий» - это жестко на C++ 11 lambdas. Они не являются «правильными» закрытиями, поскольку они не продлевают жизнь переменных, которые они захватывают (поэтому вы не можете, например, вернуть захват лямбда из функции, в которой она определена, что разрешено некоторыми/многими языками). Но это своего рода закрытие. –

Смежные вопросы