2016-04-04 1 views
1

Ich weiß, dass dies in C erlaubt ist, aber ich bin es gewohnt, den Wert einer Variablen, die als Wert übergeben wird, nicht zu aktualisieren.Sollte ich den Wert eines Funktionsparameters ändern?

In meinem "coding style" wird ein Parameter, der als Wert übergeben wird, nicht geändert. Ich meine, dass ich das vorziehen:

void func(int var) 
{ 
    int locVar = var; 

    if(something) 
    { 
     locVar = locVar/2; 
    } 

    // [some stuff using locVar] 
} 

über diese:

void func(int var) 
{ 
    if(something) 
    { 
     var = var/2; 
    } 

    // [some stuff using var] 
} 

Ich gehe davon aus, dass der Compiler nicht unterschiedliche Montage erzeugen, wenn die Register Optimierungen aktiviert sind, aber immer noch, ist es eine gute Grund, eines der beiden Code-Snippets zu bevorzugen?

+1

Ja, die Änderung der Parameter ist etwas fehleranfälliger. Auch im Debug werden Sie nicht wissen, was der ursprüngliche Wert eines Parameters ist, sondern dessen tatsächlicher Wert. Sie tun nicht # 1 (richtig) wegen Compiler und/oder Performance, sondern für sich selbst. –

+3

IMO Parameter ändern ist nicht schlecht Codierungsstil. Es liegt ganz bei Ihnen. –

+1

@Plouff Der einzige Grund für die Verwendung des ersten Ansatzes besteht darin, dass der ursprüngliche Wert mehrmals verwendet wird. Ansonsten muss keine neue lokale Variable eingeführt werden. Funktionsparameter sind bereits seine lokalen Variablen. –

Antwort

0

Je mehr Variablen eingeführt werden, desto weniger lesbar und komplizierter wird der Code sein.

Manchmal ist es sogar schwierig, zwei Namen für eine Entität zu erfinden, die semantisch identisch aussehen würden.

Zum Beispiel kann eine Funktionsauflistung mehrere Bildschirme belegen. In diesem Fall müssen Sie, wenn Sie einen Namen wie locVar gefunden haben, die Funktionsauflistung nach hinten scrollen, um zu bestimmen, was dieser Name bedeutet.

Außerdem kann eine Funktion mehrere Parameter haben. Wirst du neue Aliase für jeden Parameter einführen?

Für Leser Ihres Codes wird es nicht klar sein, dass Sie neue lokale Variablen nur eingeführt haben, um Ihren Kodierungsstil zu unterstützen. Sie können zum Beispiel denken, dass Sie die Funktion geändert haben und vergessen haben, Variablen zu entfernen, die nicht mehr notwendig sind :)

Betrachten Sie zum Beispiel eine rekursive Funktion, die die Summe der Ziffern einer Zahl berechnet.

unsigned int sum(unsigned int x) 
{ 
    const unsigned int Base = 10; 

    unsigned int digit = x % Base; 
    return digit + ((x /= Base) == 0 ? 0 : sum(x)); 
         ^^^^^^^^^^^^^ 
} 

oder das kann wie

unsigned int sum(unsigned int x) 
{ 
    const unsigned int Base = 10; 

    return x % Base + (x/Base == 0 ? 0 : sum(x/Base)); 
} 

geschrieben werden Was ist der Zweck ist es, eine neue lokale Variable als Alias ​​von x in dieser Funktion einzuführen?

unsigned int sum(unsigned int x) 
{ 
    const unsigned int Base = 10; 

    unsigned int y = x; 
    unsigned int digit = y % Base; 
    return digit + ((y /= Base) == 0 ? 0 : sum(y)); 
} 

Was mich dann die erste Funktion Implementierung ohne die Zwischengröße y ist klar. Die rekursive Natur der Funktion ist sichtbarer, wenn dieselbe Variable x verwendet wird.

Wenn Sie darauf hinweisen möchten, dass ein Parameter in einer Funktion nicht geändert wird, können Sie die Funktion mit dem Parameter mit dem Qualifier const deklarieren oder definieren.

Zum Beispiel

unsigned int sum(const unsigned int x) 
{ 
    const unsigned int Base = 10; 

    return x % Base + (x/Base == 0 ? 0 : sum(x/Base)); 
} 

In C++ Funktionsaufrufe aussehen könnte

#include <iostream> 

constexpr unsigned int sum(const unsigned int x) 
{ 
    const unsigned int Base = 10; 

    return x % Base + (x/Base == 0 ? 0 : sum(x/Base)); 
} 

int main() 
{ 
    std::cout << sum(123456789) << std::endl; 
    int a[sum(123456789)]; 

    std::cout << sizeof(a) << std::endl; 
}  

Die Programmausgabe

ist
45 
180 
+0

Ihr erstes Beispiel ist nicht zwingend; Es wird dem Funktionsparameter sowieso nicht zugewiesen. –

+0

@ JonathanLeffler Ich habe nicht verstanden, was Sie mit dem ersten Beispiel meinen? –

+0

Ich meine, dass die Frage über das Ändern des Wertes eines Funktionsparameters durch Zuweisung ist, aber Ihr Code dem Funktionsparameter nicht zuweist. Es ist jedoch schwierig, schnell ein gutes Beispiel zu finden. –

1

No.

  • Aus der Sicht eines Computers - kein Unterschied. Optimierung wird den Job machen.
  • Aus persönlicher Sicht - eine Frage des Geschmacks
  • Aus einer Meta-Ansicht - nicht setzt up Fallen

Sehr häufig anfängliche Parameterwerte mehrmals in einer Funktion benötigt werden, die häufige Stil besteht also nicht darin, Parameter zu überschreiben. Es ist sehr praktisch, die Werte zum Debuggen, Protokollieren von Nachrichten ("wrote n Bytes"), in Fangklauseln usw. verfügbar zu haben. Da dies mehr oder weniger üblich ist, könnte ein Betreuer Ihre itsy-bitsy-vorzeitige Optimierung leicht übersehen. Solche Optimierungen waren im Zeitalter von nicht optimierenden C-Compilern üblich, heutzutage sind sie nur "weil-ich-kann". Denken Sie daran, wir schreiben Code, damit er von Menschen gelesen werden kann. Compiler können das trotzdem tun.

+0

Das sind genau die Gründe, warum ich Parametervariablen nie geändert habe. Ich hätte nie gedacht, das wäre so eine Frage des Geschmacks! – Plouff

1

Gibt es einen guten Grund, eines der beiden Code-Snippets zu bevorzugen?

1) Compiler sind nicht gleich. int locVar = var;kann schneller Code erstellen. (Ich war überrascht, dass dies in einer bestimmten Anwendung wahr ist.) Dies ist eine lokale oder Mikrooptimierung und ist nur in ausgewählten Fällen nützlich und kann natürlich eine andere Leistung zur Folge haben, wenn sie mit anderen Optionen oder auf einem anderen Rechner kompiliert wird.

2) Weniger ist besser. Einführung eines Synonyms wie in int locVar = var; ist mehr Code und mehr Variablen zu verstehen und zu pflegen. Normalerweise das ist weniger hilfreich.

3) Beide Code-Snippets generieren gültigen Code. Das ist also ein Stilproblem. Wenn Ihre Kodierungsgruppe eine entsprechende Kodierungsrichtlinie hat, sollten Sie dem folgen, um aus trivialen Gründen anders zu sein.

Gründe auswählen, um eine der anderen vorzuziehen: Ja. Starke Gründe: Im Allgemeinen nein. Im Zweifelsfall, welcher Weg zu gehen ist, gewinnt der leicht zu wartende (IMO).

+0

Also, zusammenfassend, würden Sie nicht extra Variable verwenden, wenn dies von einer Codierungsrichtlinie oder in seltenen Fällen als Optimierung für einige Compiler erforderlich ist. Ich hätte nicht gedacht, dass das Kopieren von Variablen einen Overhead in Bezug auf die Wartbarkeit verursachen würde. Es ist eine interessante Sichtweise! – Plouff