rotacion operadores operaciones manipular manipulacion derecha corrimiento con como ccs bitwise c++ operator-overloading associativity

c++ - operaciones - operadores de bits java



¿Cuándo el operador<< se refiere al operador de inserción y cuándo al desplazamiento a la izquierda a nivel de bits? (6)

Esto dará como resultado 10, y el operador << se refiere al desplazamiento a la izquierda.

cout << ab () << aab << endl;

Esto se debe al hecho de que el orden de evaluación de los operandos no está especificado. Con clang da salida a 11, pero con gcc da salida a 10.

Tu codigo:

cout << a.b() << a.a.b << endl;

puede ser reemplazado con:

std::cout.operator<<(a.b()).operator<<(a.a.b);

clang primero evalúa ab() luego aab , g ++ lo hace al revés. Como tu ab() modifica las variables, obtienes diferentes resultados.

Cuando reescribes tu código como:

cout << a.b(); cout << a.a.b ;

luego tiene dos declaraciones de expresiones completas, no hay ningún comportamiento no especificado aquí relacionado con la evaluación del operando. Entonces siempre obtienes el mismo resultado.

¿Cuándo el operator << refiere al operador de inserción y cuándo se refiere al desplazamiento a la izquierda a nivel de bits?

Esto dará como resultado 10 , y el operator << refiere al desplazamiento a la izquierda.

cout << a.b() << a.a.b << endl;

Y esto dará como resultado 11 , el operator << refiere al operador de inserción.

cout << a.b(); cout << a.a.b ;

Estoy confundido, ¿cuándo el operator << (cuando se usa con cout ) se referirá al operador de cambio a la izquierda?

#include <iostream> using namespace std; class A { public: A() { a.a = a.b = 1; } struct { int a, b; } a; int b(); }; int A::b(){ int x=a.a; a.a=a.b; a.b=x; return x; }; int main(){ A a; a.a.a = 0; a.b(); cout << a.b() << a.a.b << endl; // ????? return 0; }


El problema con el que se enfrenta no tiene que ver con el operador <<. En cada caso, se llama al operador de inserción.

Sin embargo, se enfrenta a un problema relacionado con el orden de evaluación en la línea de comandos.

cout << a.b() << a.a.b << endl;

La función ab() tiene un efecto secundario. Intercambia los valores aaa y aab Por lo tanto, es evidente que se llama ab () antes o después de evaluar el valor ov aab .

En C ++, el orden de evaluación no está especificado, vea cppreference.com para una discusión más detallada.


En su caso, todos los operator << s son operadores de inserción de flujo de salida porque su argumento izquierdo es de tipo ostream& , y se agrupan de izquierda a derecha.

La diferencia en la salida se debe al orden de evaluación de los argumentos de la función:

cout << a.b() << a.a.b

es

operator<<(operator<<(cout, a.b()), a.a.b)

así que la salida depende de cuál de aab o ab() se evalúa primero. Esto no está especificado por el estándar actual (C ++ 14), por lo que también podría obtener 11 .

AFAIK en C ++ 17 11 será el único resultado válido para ambos casos porque impone una evaluación de izquierda a derecha de los parámetros de la función.

Actualización: esto parece no ser cierto, ya que el comité decidió (a partir de N4606 ) ir con la evaluación de parámetros de secuencia indeterminada mencionada en la parte inferior de P0145R2 . Ver [expr.call] / 5.

Update2: Ya que estamos hablando de operadores sobrecargados aquí, se aplica [over.match.oper] / 2 en N4606, que dice

Sin embargo, los operandos se secuencian en el orden prescrito para el operador integrado.

Entonces, de hecho, el orden de evaluación estará bien definido en C ++ 17. Este malentendido aparentemente ha sido predicho por los autores de P0145:

No creemos que tal no determinismo aporte ningún beneficio de optimización adicional sustancial, pero perpetúa la confusión y los peligros en torno al orden de las evaluaciones en las llamadas a funciones.


Esta llamada:

cout << a.b() << a.a.b << endl;

primero considerará:

cout << a.b()

que corresponden al operador de inserción y devuelve una referencia a cout. Así, la instrucción se convertirá en:

(returned reference to cout) << a.a.b

que nuevamente llamará al operador de inserción y así sucesivamente ...

Si tu instrucción fue:

cout << (a.b() << a.a.b) << endl;

la parte entre paréntesis se consideraría primero:

a.b() << a.a.b

esta vez, tiene un operador entre 2 int : el compilador solo puede resolverlo como una llamada al operador de bitwise.


Los operadores binarios, como << , tienen dos propiedades que definen su uso: precedencia (operador) y asociatividad (izquierda o derecha). En este caso, la asociatividad es la clave y, ver, por ejemplo, http://en.cppreference.com/w/c/language/operator_precedence , el operador << tiene asociatividad de izquierda a derecha, por lo que están secuenciados (como si entre paréntesis) de izquierda a derecha:

((cout << a.b()) << a.a.b) << endl;

o en palabras secuenciadas como cout << ab() luego << aab y luego << endl .

Después de esta secuencia, la sobrecarga del operador tiene efecto en cada invocación de << con los tipos dados, lo que determina la sobrecarga a la que se llama y, por lo tanto, si es una operación cout o un turno.


Sin paréntesis, los operandos en ambos lados de la << determinan el significado: int << int == shift , stream << any == insertion . Esta ''reutilización'' del operador puede ser confusa, no es así. Pero puede resolver ambigüedades usando paréntesis: stream << (int << int) == "int"