¿Cuál es el uso correcto del operador de coma?

Vi este código:

if (cond) { perror("an error occurred"), exit(1); } 

¿Por qué harías eso? ¿Por qué no solo?

 if (cond) { perror("an error occurred"); exit(1); } 

En su ejemplo, no sirve ningún motivo. En ocasiones es útil cuando se escribe como

 if(cond) perror("an error occured"), exit(1) ; 

– entonces no necesitas llaves. Pero es una invitación al desastre.

El operador de coma debe poner dos o más expresiones en una posición donde la referencia solo permita una. En su caso, no hay necesidad de usarlo; en otros casos, como en un ciclo while, puede ser útil:

 while (a = b, c < d) ... 

donde la "evaluación" real del ciclo while se rige únicamente en la última expresión.

Los casos legítimos del operador de coma son raros, pero existen. Un ejemplo es cuando desea que ocurra algo dentro de una evaluación condicional. Por ejemplo:

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

También se puede usar en lugares donde solo puede colocar una sola expresión, pero quiere que sucedan dos cosas. Por ejemplo, el siguiente bucle incrementa xy decrementa y en el tercer componente del bucle for:

 int x = 0; int y = some_number; for(; x < y; ++x, --y) { // Do something which uses a converging x and y } 

No busques su uso, pero si es apropiado, no tengas miedo de usarlo, y no te vuelvan loco si ves a alguien más usándolo. Si tiene dos cosas que no tienen ninguna razón para no ser declaraciones separadas, conviértalas en declaraciones separadas en lugar de usar el operador de coma.

El uso principal del operador de coma es ofuscación; permite hacer dos cosas donde el lector solo espera una. Uno de los usos más frecuentes, la adición de efectos secundarios a una afección, cae dentro de esta categoría. Sin embargo, hay algunos casos que podrían considerarse válidos:

El que se usó para presentarlo en K & R: incrementando dos variables en un ciclo for . En el código moderno, esto podría ocurrir en una función como std::transform , o std::copy , donde un iterador de salida se incrementa de manera simultánea con el iterador de entrada. (Más a menudo, por supuesto, estas funciones contendrán un ciclo while, con incrementos en declaraciones separadas al final del ciclo. En tales casos, no tiene sentido usar una coma en lugar de dos instrucciones).

Otro caso que me viene a la mente es la validación de datos de los parámetros de entrada en una lista de inicializadores:

 MyClass::MyClass( T const& param ) : member( (validate( param ), param) ) { } 

(Esto supone que validate( param ) arrojará una excepción si algo está mal.) Este uso no es particularmente atractivo, especialmente porque necesita los paréntesis adicionales, pero no hay muchas alternativas.

Finalmente, a veces he visto la convención:

 ScopedLock( myMutex ), protectedFunction(); 

, lo que evita tener que inventar un nombre para ScopedLock . A decir verdad, no me gusta, pero lo he visto utilizado, y la alternativa de agregar llaves adicionales para asegurar que ScopedLock se ScopedLock inmediatamente tampoco es muy bonita.

Esto se puede entender mejor tomando algunos ejemplos:

Primero: Considera una expresión:

  x = ++j; 

Pero por el momento, si necesitamos asignar un valor de depuración temporal, entonces podemos escribir.

  x = DEBUG_VALUE, ++j; 

Segundo:
Coma , operadores se utilizan con frecuencia en for() -loop, por ejemplo:

 for(i = 0, j = 10; i < N; j--, i++) // ^ ^ here we can't use ; 

Tercero:
Un ejemplo más (de hecho uno puede encontrar haciendo esto interesante):

 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; 

También se puede hacer en un solo paso;

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

PD: También puede ser interesante saber que a veces es desastroso de usar , operador. Por ejemplo, en la pregunta uso de Strtok, el código no funciona , por error, OP olvidó escribir el nombre de la función y en lugar de escribir tokens = strtok(NULL, ",'"); , escribió tokens = (NULL, ",'"); y no obtenía el error de comstackción, pero es una expresión válida que tokens = ",'"; causó un ciclo infinito en su progtwig.

El operador de coma permite agrupar la expresión donde se espera.

Por ejemplo, puede ser útil en algunos casos:

 // In a loop while ( a--, a < d ) ... 

Pero en tu caso no hay razón para usarlo. Será confuso ... eso es todo ...

En tu caso, es solo para evitar las llaves:

 if(cond) perror("an error occurred"), exit(1); // => if (cond) { perror("an error occurred"); exit(1); } 

Un enlace a una documentación del operador de coma .

En su caso, el operador de coma es inútil ya que podría haber sido utilizado para evitar llaves , pero no es el caso ya que el escritor ya los ha puesto. Por lo tanto, es inútil y puede ser confuso .

Parece que hay pocos usos prácticos del operador, ().

Bjarne Stroustrup, El diseño y la evolución de C ++

La mayor parte del uso frecuente de la coma se puede encontrar en el artículo de wikipedia Comma_operator # Uses .

Un uso interesante que he descubierto al usar el boost :: assign , donde había sobrecargado juiciosamente al operador para hacer que se comportara como una lista de valores separados por comas que pueden ser empujados al final de un objeto vectorial

 #include  // for 'operator+=()' using namespace std; using namespace boost::assign; // bring 'operator+=()' into scope { vector values; values += 1,2,3,4,5,6,7,8,9; // insert values at the end of the container } 

Desafortunadamente, el uso anterior, que era popular para la creación de prototipos, ahora parecería arcaico una vez que los comstackdores comiencen a admitir la inicialización uniforme.

Entonces eso nos devuelve a

Parece que hay pocos usos prácticos del operador, ().

Bjarne Stroustrup, El diseño y la evolución de C ++

El boost::assign sobrecarga al operador de coma en gran medida para lograr este tipo de syntax:

 vector v; v += 1,2,3,4,5,6,7,8,9; 

Podría ser útil para el operador del itinerario si desea ejecutar dos o más instrucciones cuando la condición es verdadera o falsa . pero tenga en cuenta que el valor de retorno será la expresión más correcta debido a la regla de evaluación de izquierda a derecha del operador de coma (es decir, dentro del paréntesis)

Por ejemplo:

 a