2009-08-06 10 views
5

Rozważmy następujący contrived przykład:Stylistic pytanie o powrocie void

void HandleThat() { ... } 

void HandleThis() 
{ 
    if (That) return HandleThat(); 
    ... 
} 

Ten kod działa dobrze, i jestem pewny, że to Spec-ważne, ale (być może na własną rękę) rozpatruje ten niezwykły styl , ponieważ wywołanie wydaje się zwracać wynik funkcji, mimo że obie funkcje są prototypowane, aby były nieważne.

Zazwyczaj Spodziewam się, aby zobaczyć:

if (That) {HandleThat(); return;} 

co czuję, nie pozostawia niejasności co do tego, co się dzieje.

W jaki sposób mogę uzyskać opinię na temat tego, czy styl kodowania zwrotnego jest mylący lub problematyczny? Ma charakter idiomu; powinienem użyć tego lub go unikać?

Generalnie staram się zachować jasność i używać drugiego stylu. Z drugiej strony jest czystość pierwszej formy, która mnie do tego w pewnym sensie przyciąga.

+0

W przypadku jakichkolwiek odsetek, moje faktyczne wykorzystanie tego jest w określonych okolicznościach zwolnione za kaucją do klasy macierzystej. Viz: void derivedclass :: f (...) {if (bail) return parentclass :: f (...); ...} –

Odpowiedz

13

Zgadzam się z tobą, pierwszy styl jest mylący, ponieważ istnieje implikacja, że ​​zwracana jest pewna wartość. W rzeczywistości musiałem go przeczytać kilka razy , ponieważ z tego.

Po powrocie z funkcji prototypowanej pustej, powinien to być tylko powrót;

+0

+1 Nie widzę żadnego powodu, dla którego ktoś miałby korzystać z pierwszej konwencji po powrocie. – Eric

+0

Uzgodnione, drugie jest bardziej intuicyjne i czytelne - na pewno warte kilku dodatkowych znaków. – Amber

+1

Ten ostatni jest bardziej intuicyjny i czytelny. Jednak pierwszy jest również bardzo czytelny, a to, czego się w nim domyślacie, jest poprawne. Więc nie łamie to twojej intuicji. –

11

Jest to prawdopodobnie trochę zbyt sprytne. Jeśli linia ta skończy się o więcej niż kilka linii od góry funkcji, będzie to mylące. Oznacza to również, programista patrząc na kod będzie trzeba skorelować

return HandleThat(); 

z typem void powrotnej i dowiedzieć się spryt, zanim naprawdę zrozumieć kod. Kiedy robisz więcej niż jedną rzecz w gałęzi if/else, powinieneś naprawdę używać nawiasów klamrowych i umieszczać kroki w różnych liniach. Zajmuje więcej miejsca, ale jest łatwiejsze do zrozumienia:

if (That) { 
    HandleThat(); 
    return; 
} 
3

Nigdy wcześniej tego nie widziałem.

Ma tę zaletę, że wygląda jak wspólny idiom dla non-pustych typów zwrotnych, więc czyta się bardzo łatwo ...

I nie zmieni, chyba że ktoś może pokazać, że jest ona nieważna.

4

Reguły języka C mówią, że jeśli funkcja deklarowana jako zwracająca pustka próbuje zwrócić wyrażenie, wyrażenie nie zostanie ocenione.

http://c0x.coding-guidelines.com/6.8.6.4.html

+0

Oba style generują identyczne wyniki. Dla tego kodu: void a() {printf ("Świat! \ N");} void b() {printf ("Hello"); return a(); } otrzymujesz Hello World zgodnie z oczekiwaniami. –

+1

Sprawdziłem, że z pełną optymalizacją i usuwaniem przy użyciu GCC 4.0 –

+0

Myślę, że jego niezdefiniowane zachowanie technicznie. – sylvanaar

2

Wierzę, że pierwsza wersja jest przede wszystkim możliwość łatwość programowania szablonu. Jeśli HandleThat zwróci typ T, który może być nieważny, wygodnie jest użyć pierwszej wersji.

Ale w "normalnych" przypadkach druga wersja jest jaśniejsza i wolałbym to.