2011年7月26日 星期二

Goto使用的時機點?

從開始學寫程式開始, 就有一種東西老師總會千叮嚀萬交待的說, 千萬不要使用(亂用)goto, 那這東西為何而來呢?其實要了解goto, 得先從組語開始了解起, 組語裡因為接近真實cpu操作的指令, 所以跳來跳去是很正常的一件事, 為了這個原因, 當初在設計C的大老, 自然就會引近相同的功能, 那就是goto啦..
仔細看一下各種語言裡, 雖然大多數的人現在都很少用到goto, 但為何在每個語言裡都還是把goto列為保留字呢? 原因就在於他還是有一些用途的...
Java裡不能使用goto, 但在Java的原文教材裡, 有這麼一句話, [Java編程語言不使用關鍵字goto和const], 只是Java還是把goto列為了保留字, 不談各語言間的優缺點, 我們來看看如何使用goto讓程式變得更簡潔, 看完之後再來說, 為什麼goto還是有其存在的必要性...



main()
{
    int i,sum=0;
    i=0;
    loop:
    if(i
        sum=sum+1;
        i++;
        goto loop;
    }
    printf("%d",sum);
}
上面的程式很醜吧, 為何不用for, 其實要是理解for在compile之後的組語, 相信你也會寫出這樣的程式, 但這不是重點, 重點在下面...
那何時該使用goto呢?
通常在一個function裡我們會用到new, malloc等即時生成的記憶體區塊, 但在這個function結束前我們會把記憶體回收, 但在程式裡我們可能不只在一個地方結束這個function, 所以在結束前都要delete, free這些記憶體, 這樣看起來你的程式就會像這樣..
int myFunction() {
    if(...) {
        delete ...;
        .... = NULL;
        return 0;
    }
    if(...) {
        delete ...;
        ... = NULL;
        return 0;
    }
    ....
    delete ...;
    .... = NULL;
    return 0;
}
那我們如何改寫呢?一定有人說, 看過refactor之後, 我知道就是把他獨立出來一個function做為了一個小function去clean up這些東西.......
這麼說沒錯, 但有時這些小function反而會讓你更難追code..
所以..大師們的建議是這樣的..
    if(...) {
        goto cleanup;
    }
    if(...) {
        goto cleanup;
    }
    ....
cleanup:
        delete ...;
        ... = NULL;
        return 0;
}
嗯..這樣不但沒有多出function, 而且是不是也看得更清楚了??

沒有留言: