2016-02-12 11 views
1

Я пишу компилятор упражнений, а lookup_helper (key, current) возвращает указатель на некоторый символ, если он найден в текущей области. цикл for() циклически перемещается по всем областям и ищет какой-либо символ, пока не найдет его и не вернет. в противном случае возвращается nullptr.Возврат, если значение функции равно нулю

Symbol * lookup() 
    { 

    //.... 
    //.... 

    //search all scopes 
    for (int i = Scopes.size(); i > 0; i--) 
      { 
       Scope current = Scopes[i - 1]; 

       if (lookup_helper(key, current)) //not good design 
        return lookup_helper(key, current); //calling second time 

      } 
     return nullptr; //not found 
    } 

Не этот код вызывает lookup_helper() дважды? один раз в if() и один раз в обратном? У меня есть решение этой проблемы, но я ищу более элегантное решение, которое вызывает lookup_helper только один раз (также я не хочу создавать некоторую переменную для хранения возвращаемого значения). Возможно, то, что я прошу, невозможно, потому что мне нужно будет перейти к выполнению кода, чтобы определить, возвращает ли lookup_helper значение nullptr или нет.

Что бы себе элегантна: (не работает, как это)

for (int i = Scopes.size(); i > 0; i--) 
     { 
      Scope current = Scopes[i]; 

      return (ifnotnull) lookup_helper(key, current); 

     } 
+4

Почему бы не использовать локальную переменную? – Jarod42

+0

В OP я говорю, что это не то, что я хотел бы сделать. Я ищу особенность языка (что-то вроде лямбды или чего-то еще), что позволяет ему вызывать функцию только один раз – user3465668

+0

Каким образом последний пример изящный? Все еще вызов 'lookup_helper' дважды, плюс проверка (попытка) дважды сейчас? – LogicStuff

ответ

1

С локальной переменной в самой внутренней области видимости, вы можете сделать

for (int i = Scopes.size(); i > 0; i--) { 
    if (auto ret = lookup_helper(key, Scopes[i])) { 
     return ret; 
    } 
} 

или более традиционный

for (int i = Scopes.size(); i > 0; i--) { 
    auto ret = lookup_helper(key, Scopes[i]); 
    if (ret) { 
     return ret; 
    } 
} 
+0

, что возвращает if if() statement? true, если ret не равен нулю? Мне нравится это – user3465668

+0

@ user3465668 Функция 'lookup_helper' возвращает указатель, поэтому' auto ret' - тип указателя. 'Operator =' возвращает ссылку на измененный объект (т. Е. Указатель). Наконец, 'T * ptr = nullptr; if (ptr) {...} 'иллюстрирует, почему работает вышеуказанное' if (auto ret = lookup_helper (...)) '. –

2

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

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

... 
Symbol *symbol = lookup_helper(key, current); 
if (symbol != nullptr) 
    return symbol; 
.... 
0

Да ваш код будет вызывать lookup_helper дважды. Простым решением является сохранение результата в локальной переменной:

... 
for(auto & scope : Scopes) { 
    auto ret = lookup_helper(key, scope); 
    if(ret) return ret; 
} 
... 
Смежные вопросы