如果函数值为空,则返回

Return if function value is null

本文关键字:返回 函数 如果      更新时间:2023-10-16

我正在编写一个练习编译器,如果在当前范围内找到某个符号,则lookup_helper(键,当前(返回指向某个符号的指针。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); 
        }

是的,您的代码调用lookup_helper两次。一些编译器可能能够消除第二次调用,如果他们知道函数是"纯的"(使用 GCC 术语(。但是,在C++中,它是最好手动和显式完成的"优化"之一。

至于如何避免第二次调用,通常是通过在尝试分析之前将结果存储在中间变量中来完成的。

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

在最内部的范围内使用局部变量,您可以这样做

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;
    }
}

是的,您的代码将调用lookup_helper两次。一个简单的解决方案是将结果存储到局部变量中:

...
for(auto & scope : Scopes) {
    auto ret = lookup_helper(key, scope);
    if(ret) return ret;
}
...