habe ich diesen Code:Was ist der richtige Umgang mit dem Komma-Operator?
if (cond) {
perror("an error occurred"), exit(1);
}
Warum Sie das tun würde? Warum nicht einfach:
habe ich diesen Code:Was ist der richtige Umgang mit dem Komma-Operator?
if (cond) {
perror("an error occurred"), exit(1);
}
Warum Sie das tun würde? Warum nicht einfach:
In Ihrem Beispiel dient es überhaupt keinen Grund. Es ist gelegentlich nützlich, wenn sie als
if(cond)
perror("an error occured"), exit(1) ;
geschrieben - dann müssen Sie nicht geschweiften Klammern müssen. Aber es ist eine Einladung zum Desaster.
Der Komma-Operator soll zwei oder mehr Ausdrücke in eine Position setzen, in der die Referenz nur eins erlaubt. In Ihrem Fall besteht keine Notwendigkeit, es zu verwenden; in anderen Fällen, wie zum Beispiel in einer while-Schleife, kann es nützlich sein:
while (a = b, c < d)
...
, wo die eigentliche „Auswertung“ der while-Schleife nur auf dem letzten Ausdruck geregelt.
Mit anderen Worten, der Komma-Operator ist hauptsächlich nützlich für die Verschleierung. –
Ein Komma-Operator kombiniert zwei oder mehr * Ausdrücke *, keine Anweisungen. –
@Keith: Ta, du hast Recht. Bearbeitet. – usr2564301
Legitime Fälle des Komma-Operators sind selten, aber sie existieren. Ein Beispiel ist, wenn in einer bedingten Auswertung etwas passieren soll. Zum Beispiel:
std::wstring example;
auto it = example.begin();
while (it = std::find(it, example.end(), L'\\'), it != example.end())
{
// Do something to each backslash in `example`
}
Es auch dort eingesetzt werden kann, wo man nur einen einzigen Ausdruck platzieren können, will aber zwei Dinge passieren. Zum Beispiel werden die folgenden Schleifen Schritten x und y Verringerungen in der für dritte Komponente der Schleife:
int x = 0;
int y = some_number;
for(; x < y; ++x, --y)
{
// Do something which uses a converging x and y
}
Gehen Sie nicht für die Verwendung von ihm suchen, aber wenn es angemessen ist, haben Sie keine Angst, es zu benutzen, und nicht für eine Schleife geworfen werden, wenn Sie jemanden sehen, der es benutzt. Wenn Sie zwei Dinge haben, die keinen Grund haben, keine separaten Anweisungen zu sein, machen Sie sie separate Anweisungen, anstatt den Komma-Operator zu verwenden.
Billy, ist nicht das Ergebnis eines Auftrags seinen letzten Wert? Da Sie es sofort nach dem Zuweisen neu bewerten, können Sie den Test ohne den Komma-Operator hinzufügen. (Es ist jedoch ein gültiges Beispiel.) – usr2564301
@Jongware: Ja, in diesem speziellen Fall könnten Sie das tun. Persönlich finde ich das Komma besser lesbar als Aufgaben in Bedingungen zu setzen (wegen der möglichen Verwechslung von '=' vs. '=='). Aber das ist eine Stilwahl. –
Ta. Normalerweise versuche ich, * beiden * Konstruktionen aus Gründen der Lesbarkeit zu vermeiden ;-) – usr2564301
Der Komma-Operator ermöglicht das Gruppieren von Ausdrücken, wo einer erwartet wird.
Zum Beispiel kann es in einigen Fällen sinnvoll sein:
// In a loop
while (a--, a < d) ...
Aber in Ihnen Fall gibt es keinen Grund, es zu benutzen. Es wird verwirrend sein ... das ist es ...
In Ihrem Fall ist es nur geschweifte Klammern zu vermeiden:
if(cond)
perror("an error occured"), exit(1);
// =>
if (cond)
{
perror("an error occured");
exit(1);
}
Ein Link zu einer comma operator Dokumentation.
Ihr zweites Beispiel ('int a = 4, b = 5;') ist keine Zuweisung, sondern Initialisierung, der Operator ist kein Kommaoperator (für alle gibt es ein Komma, das die beiden Definitionen trennt) –
@ JonathanLeffler Sie haben Recht, nur entfernt es. –
In Ihrem Fall ist der Komma-Operator nutzlos, da er hätte verwendet werden können, um curly braces zu vermeiden, aber das ist nicht der Fall, da der Schreiber sie bereits gestellt hat. Daher ist es nutzlos und kann verwirrend sein.
Die Hauptanwendung des Komma-Operators ist die Verschleierung; es erlaubt, zwei Dinge zu tun, wo der Leser nur einen erwartet. Einer der häufigsten verwendet — Hinzufügen von Nebenwirkungen zu einem Zustand, fällt unter dieser Kategorie.Es gibt ein paar Fälle, die als gültig angesehen werden könnten, jedoch:
Die eine, die verwendet wurde, es in K & R präsentieren zu können: Erhöhen zwei Variablen in einer for
Schleife. In modernem Code könnte dies in einer -Funktion wie std::transform
oder std::copy
auftreten, wobei ein Ausgangsiterator gleichzeitig mit dem Eingangsiterator inkrementiert wird. (Öfter von Natürlich werden diese Funktionen enthalten eine while
Schleife mit den Inkrementierungen in getrennten Erklärungen am Ende der Schleife. In einem solchen Fällen gibt es keinen Punkt ein Komma anstatt zwei Aussagen in Verwendung.)
ein weiterer Fall, der in den Sinn kommt, ist die Datenvalidierung von Eingabe in einer Initialisiererliste Parameter: (. Dies setzt voraus, dass validate(param)
eine Ausnahme auslösen, wenn etwas nicht in Ordnung ist)
MyClass::MyClass(T const& param)
: member((validate(param), param))
{
}
Diese Verwendung ist nicht besonders attraktiv ist insbesondere , da es die zusätzlichen Klammern benötigt, aber es gibt nicht viele Alternativen.
Schließlich habe ich manchmal die Konvention gesehen:
ScopedLock(myMutex), protectedFunction();
, die einen Namen für die ScopedLock
erfinden vermeidet. Um zu sagen, die Wahrheit, ich mag es nicht, aber ich habe es gesehen, und die Alternative Hinzufügen zusätzlicher Klammern, um sicherzustellen, dass die ScopedLock
ist sofort zerstört ist nicht sehr schön.
"* Die Hauptanwendung des Komma-Betreibers ist Verschleierung *" - Ich glaube nicht, dass das stimmt. Es kann sicherlich * so verwendet werden, aber es gibt viele legitime (Wenn Sie Ihre Beobachtungen auf Code beschränken, der von Anfängern geschrieben wurde, haben Sie wahrscheinlich Recht.) –
@KeithThompson Der Hauptgebrauch, den ich gesehen habe, war die Verschleierung. Ich gebe einige Beispiele, wo seine Verwendung gerechtfertigt sein könnte. Aber wo die Alternativen sind nicht wirklich klarer als mit dem Komma-Operator es wurde viel missbraucht, und die meisten Beispiele, die in den anderen Beispielen gepostet wurden, sind Missbrauch. (Interessanterweise wird es häufiger in C++ als in C missbraucht. In C++ können Sie es überlasten, und _all_ der Überlastung, die ich gesehen habe, ist Missbrauch.) –
Dies kann besser verstanden werden durch einige Beispiele unter:
Erstens: Betrachten wir einen Ausdruck:
x = ++j;
Aber vorerst, wenn wir einen vorübergehend Debug-Wert zuweisen müssen, dann wir können schreiben.
x = DEBUG_VALUE, ++j;
Zweitens:
Comma ,
Operatoren werden häufig in for()
verwendet -loop zB:
for(i = 0, j = 10; i < N; j--, i++)
// ^ ^ here we can't use ;
Drittens:
Ein weiteres Beispiel (eigentlich kann man diese interessant finden zu tun) :
if (x = 16/4), if remainder is zero then print x = x - 1;
if (x = 16/5), if remainder is zero then print x = x + 1;
Es kann auch in einem einzigen Schritt durchgeführt werden;
if(x = n/d, n % d) // == x = n/d; if(n % d)
printf("Remainder not zero, x + 1 = %d", (x + 1));
else
printf("Remainder is zero, x - 1 = %d", (x - 1));
PS: Es kann auch interessant zu wissen, dass es manchmal katastrophal ,
Operator zu verwenden.Zum Beispiel in der Frage Strtok usage, code not working, versehentlich, vergaß OP, Namen der Funktion zu schreiben und anstatt tokens = strtok(NULL, ",'");
zu schreiben, schrieb er tokens = (NULL, ",'");
und er erhielt nicht Kompilierungsfehler - aber sein ein gültiger Ausdruck, dass tokens = ",'";
eine Endlosschleife in seinem Programm verursachte .
@Sakham Danke Sakham! –
Ich denke, Ihr zweites Beispiel ('for') macht 99% des legitimen Komma-Operators aus. – ugoren
@ugoren Ja. andere Verwendungen von ',' sind nur eine Art von Verschleierung, z.B. 3rr Beispiel. –
Es scheint nur wenige praktische Verwendungen von Operator,().
Bjarne Stroustrup, das Design und die Entwicklung von C++
Die meisten der oft Verwendung von Komma kann Comma_operator#Uses in Wikipedia-Artikel herausgefunden werden.
Eine interessante Nutzung ich herausgefunden haben, bei der Verwendung der boost::assign, wo es umsichtig den Betreiber überlastet war es zu machen verhalten, als eine durch Komma Liste von Werten getrennt, die an das Ende eines Vektorobjekt geschoben werden kann
#include <boost/assign/std/vector.hpp> // for 'operator+=()'
using namespace std;
using namespace boost::assign; // bring 'operator+=()' into scope
{
vector<int> values;
values += 1,2,3,4,5,6,7,8,9; // insert values at the end of the container
}
Leider ist die obige Verwendung, die für das Prototyping populär war, würde nun archaisch aussehen einmal Compiler Uniform Initialization
Unterstützung von Start, dass So lässt uns zurück zu
Es scheint nur wenige praktische Verwendungen des Operators() zu geben.
Bjarne Stroustrup, das Design und die Entwicklung von C++
Die boost::assign
Überlastungen stark der Komma-Operator diese Art von Syntax zu erreichen:
vector<int> v;
v += 1,2,3,4,5,6,7,8,9;
Es könnte für die Route Betreiber nützlich sein Wenn Sie zwei oder mehr Anweisungen ausführen möchten, wenn die Bedingung wahr oder false ist. aber denken Sie daran, dass der Rückgabewert wird der meist richtige Ausdruck aufgrund des Komma-Operator seiner nach rechts evalutaion Regel links (I in den Klammern bedeuten)
Zum Beispiel:
a<b?(x=5,b=6,d=i):exit(1);
Der Komma-Operator ist außerhalb von Ausdruck SFINAE nutzlos. – Rapptz
Ein Komma-Operator ist manchmal nützlich in Kontexten wie dem Hauptteil eines Makros, in dem Sie mehrere Operationen zu einer einzigen Anweisung kombinieren möchten. Andernfalls kann es nützlich sein, wenn Sie zwei Variablen in einer Schleife oder an einigen anderen stilisierten Stellen inkrementieren. Im Allgemeinen ist es jedoch zu vermeiden; Ein Semikolon ist besser als ein Komma. Siehe auch Fragen wie [Vorrang des Komma-Operators während der Verwendung von '?:' Operator] (http://stackoverflow.com/questions/16854007/comma-operator-precedence-while-used-with-operator) für Beispiele der Verwirrung verursacht durch den Komma-Operator. –
@ JonathanLeffler ',' wir auch häufig in For-Schleifen verwenden –