¿Todos los operadores de C ++ devuelven algo?

83

Todos los operadores de C ++ con los que he trabajado devuelven algo, por ejemplo, el +operador devuelve el resultado de la suma.

¿Todos los operadores de C ++ devuelven algo o hay algunos operadores de C ++ que no devuelven nada?

usuario8240761
fuente
7
Eso depende de qué tan estrictamente defina el término "operador".
molbdnilo
12
Esto no está obligado por el estándar; por ejemplo, puede implementar +=para regresar void, pero no se recomienda. También los operadores de llamadas a funciones pueden regresar voidy esto es válido
Mircea Ispas
Hmm. Tengo el presentimiento de que el operador de resolución de alcance ::no devuelve nada, pero tendría que consultar el estándar para asegurarme.
Yksisarvinen
2
¿El contexto de la pregunta es solo para tipos proporcionados por C ++ o también incluye tipos definidos por el usuario?
Eljay
@Eljay Solo los tipos proporcionados por C ++.
user8240761

Respuestas:

111

No, no todos los operadores devuelven algo.

Aunque probablemente no sean exactamente lo que está pensando, tenga en cuenta que las 'palabras clave' deletey delete[]C ++ son en realidad operadores ; y se definen como que tienen el voidtipo de retorno, lo que significa que no evalúan nada (que no es "algo").

Desde cppreference :

void operator delete  ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;
Adrian Mole
fuente
13
Me gusta tu respuesta, me hizo pensar en la pregunta de manera diferente. delete, delete[], throw, (void)x;Fundido, lado izquierdo del ,lado del operador, a la derecha de ,operador que produce un void, una ?:ternario que utiliza una throwpara uno de los brazos, de dfri operator void()(que sería definido por el usuario),眠りネロク's void operator()()(que sería definido por el usuario).
Eljay
10
También es confuso que el deleteoperador destruya el objeto y luego llame operator delete. Ergo, el deleteoperador y operator deleteson cosas separadas :( stackoverflow.com/a/8918942/845092
Mooing Duck
7
No estoy seguro de por qué cita las funciones de eliminación cuando habla del operador de eliminación. Pero lo que sea.
Deduplicador
4
@MooingDuck La expresión de eliminación destruye el objeto y luego llama operator delete.
NathanOliver
¿La eliminación cuenta como un operador a través de, pensé que un objeto es algo que actúa sobre un objeto que se pasa? Eliminar no necesita que se pase o se cree ningún objeto para que funcione ..... Al igual que printf .....
Yunfei Chen
82

Los operadores de tipos personalizados pueden estar sobrecargados para hacer las cosas más extrañas.

por ejemplo, el operador + devuelve el resultado de la suma.

No necesariamente:

#include <iostream>
struct foo {
    int value = 0;
    void operator+(int x) {
        value += x;
    }
};

int main () {
    foo f;
    f + 3;
}

aquí operator+ agrega el lado izquierdo al valuemiembro y su tipo de retorno es nulo. Este es un ejemplo inventado, pero, en general, no es inusual devolver algo de un operador personalizado.

El único operador que se puede sobrecargar y que tiene el requisito de devolver algo, que yo sepa, es operator->. Debe devolver un puntero sin formato o un objeto que tenga una extensión operator->.

idclev 463035818
fuente
Curiosamente, en realidad no existe ninguna restricción sobre el valor de retorno de los operadores sobrecargados. Entonces, los operadores pueden devolver lo que quieran. en.cppreference.com/w/cpp/language/operators
bracco23
5
@ braccor23 operator->es un poco especial y necesita devolver un puntero o un objeto que tenga un operator->, no estoy seguro si hay otras excepciones
idclev 463035818
1
Sí, esa es la única limitación. Ni siquiera bool para los operadores de comparación. Eso se ve realmente extraño.
bracco23
9
@ idclev463035818: Un ejemplo quizás más útil puede ser Plantillas de expresión. Por ejemplo, puede crear una biblioteca de matrices en la que operator*(Matrix const& left, Matrix const& right)no se devuelva, Matrixsino que MatrixMul, si luego se introduce en operator+(Matrix const& left, MatrixMul const& right)la operación, puede ser una combinación de multiplicar-sumar que es más eficiente que multiplicar primero y luego sumar.
Matthieu M.
1
@DarrelHoffman Cuando <<y >>están sobrecargados para las operaciones de E / S, se espera que devuelvan la transmisión para que pueda conectarlos en cascada:stream << foo << bar;
Barmar
34

Para ser quisquilloso, los operadores no devuelven nada. Son solo elementos léxicos que usamos para crear expresiones en el idioma. Ahora, las expresiones tienen tipos y pueden evaluarse a valores, y supongo que esto es lo que quiere decir con operadores que "devuelven cosas".

Y bueno, sí. Hay expresiones de C ++ con tipo void(y, en consecuencia, no se evalúan con ningún valor). Algunas son obvias, otras menos. Un buen ejemplo sería

throw std::runtime_error()

throwes una expresión de la gramática C ++. Puede usarlo en otras expresiones, por ejemplo, en la expresión condicional

return goodStatus() ? getValue() : throw std::runtime_error();

Y el tipo de expresión de lanzamiento es void. Obviamente, dado que esto solo hace que la ejecución vaya rápidamente a otra parte, la expresión no tiene valor.

StoryTeller - Unslander Monica
fuente
21

Ninguno de los operadores de C ++ integrados devuelve algo. Los operadores de C ++ sobrecargados devuelven algo en la medida en que la notación del operador es un azúcar sintáctico para una llamada de función.

Más bien, todos los operadores evalúan algo. Ese algo tiene un valor bien definido , así como un tipo . Incluso el operador de llamada de función void operator()(/*params*/)es un voidtipo.

Por ejemplo, +'a'es un inttipo con el valor de'a' codificado en su plataforma.

Si su pregunta es "¿Pueden los operadores de C ++ tener un voidtipo de retorno?" entonces la respuesta es ciertamente sí.

Betsabé
fuente
14
@ idclev463035818: Es el término retorno con el que tengo un problema. Lo único en C ++ que devuelve algo es una función. Las expresiones evalúan algo.
Betsabé
7
los operadores de tipos de clase son métodos que devuelven algo
idclev 463035818
4
Éste es un punto importante. La terminología descuidada conduce a la confusión. +1.
Pete Becker
3
@supercat: tu comentario difama a un grupo de personas trabajadoras, incluyéndome a mí. Aquellos de nosotros que escribimos el estándar nunca esperamos que los escritores de compiladores completen los detalles encuestando a otros compiladores, presentes o pasados. El objetivo del estándar era y es definir claramente la sintaxis y la semántica del lenguaje de programación C ++. Sí, el resultado no es perfecto; Hay muchos problemas abordados en el último estándar que no se abordaron en versiones anteriores. Eso proviene de la experiencia, reconociendo complicaciones que simplemente no se vieron en ese momento.
Pete Becker
3
@ Peter-ReinstateMonica: aquí hay una versión más sólida. La expresión I++no devuelve ningún valor. Si el tipo de ies un tipo definido por el usuario, esa expresión se implementa como operator++, que es una función que devuelve un valor. A eso lo llamas "azúcar sintáctico"; A eso lo llamo una distinción que tiene importantes consecuencias.
Pete Becker
12

De hecho, puede definir un operador de llamada a función para que no devuelva nada. Por ejemplo:

struct Task {
   void operator()() const;
};
眠 り ネ ロ ク
fuente
17
Puede definir a casi cualquier operador para que no devuelva nada (y enfrentarse a la ira de la multitud enojada que tendrá que mantener ese código)
Yksisarvinen
7
@Yksisarvinen pero al menos este es potencialmente útil.
Mark Ransom
11

operador void (): función de conversión definida por el usuario a void

Es posible definir la peculiar operator void()función de conversión, donde el compilador incluso le advertirá que el Tde voidla función de conversión no se utilizarán :

#include <iostream>

struct Foo {
    operator void() { std::cout << "Foo::operator void()!"; }
    // warning: conversion function converting 'Foo' to 
    //          'void' will never be used
};
    
int main() {
    Foo f;
    (void)f;            // nothing
    f.operator void();  // Foo::operator void()!
}

según lo regido por [class.conv.fct] / 1

[...] función de conversión A nunca se usa para convertir una (posiblemente cv-cualificada) objeto con el mismo tipo de objeto (posiblemente cv-cualificada) (o una referencia a la misma), a una clase base (posiblemente cv-cualificada) de ese tipo (o una referencia a la misma), o a (posiblemente cv-calificado) void. 117

( 117 ) Estas conversiones se consideran conversiones estándar a efectos de resolución de sobrecarga ([over.best.ics], [over.ics.ref]) y, por lo tanto, inicialización ([dcl.init]) y conversiones explícitas. Una conversión a voidno invoca ninguna función de conversión ([expr.static.cast]). Aunque nunca se llame directamente para realizar una conversión, dichas funciones de conversión se pueden declarar y potencialmente se pueden alcanzar a través de una llamada a una función de conversión virtual en una clase base.

Si bien, sin embargo, como se muestra arriba, aún puede invocarlo usando la .operator void()sintaxis explícita .

dfrib
fuente
4

Los operadores definidos (incorporados) por el lenguaje son tokens que se utilizan para realizar diferentes tipos de cálculos:

  • aritmética (+, -, *, /)
  • incremento / decremento (++, -)
  • asignación (=, + =, - =, * =, / =,% =, >> =, << =, & =, ^ =, | =)
  • lógica (!, &&, ||)
  • relacional (==,! =,>, <,> =, <=)
  • condicional?
  • coma

y así. La lista puede ser muy extensa.

En referencias de lenguaje como este o este , no necesariamente se hace referencia a ellos como devolviendo algo, simplemente realizando una operación aritmética o lógica. , una comparación por la cual se puede modificar una variable, etc.

Dado que esta operación da como resultado algún valor, el operador puede interpretarla como "devuelta", pero es diferente de un valor de retorno de función.

Los operadores sobrecargados, por otro lado, se pueden definir con un valor de retorno de algún tipo, incluso que puede ser nulo, así que no, no todos los operadores devuelven algún valor en C ++.

ram0nvaldez
fuente
3

Supongo que está hablando de funciones de operador y no de operadores como una unidad sintáctica del lenguaje.

Si sobrecarga operadores en cualquier tipo, en realidad puede devolver lo que desee.

Esto también tiene mucho sentido, porque operaciones como * o () a veces pueden no devolver de forma muy intuitiva su tipo de entrada. Imagínese multiplicar un tipo de número complejo por un tipo de número real. O un operador que devuelve un elemento de una colección.

También puede sobrecargar los operadores ++ y - para no devolver nada, eliminando así la mezcla extremadamente propensa a errores de efecto secundario y valor de expresión que tiene la versión estándar.

Kafein
fuente
2

No. Considere estos dos ejemplos aquí:

int multiply (int a, int b) {
   return a*b;
}

void multiply_void(int a, int b) {
   cout << a*b;
//or cout << multiply(a,b);
}

La primera función devolverá un valor entero que puede ser utilizado por otra función. El valor se devuelve y se almacena en la memoria para ser utilizado cuando sea necesario. De lo contrario, no es visible para los humanos y simplemente se sienta felizmente en la memoria.

La segunda función se enviará al dispositivo de salida predeterminado (generalmente consola). El valor devuelto por el operador de multiplicación se pasa a un dispositivo de salida. La función multiply_void no devuelve un valor real.

Gokhan Dilek
fuente
0

Todos los operadores devuelven algo. Se les llama operadores porque operan algo, por lo tanto, devolverán algo. Aquellos Operadores que no devuelvan algo no se pueden llamar operadores. O devolverán algún valor o devolverán Verdadero o Falso según la situación.

Alby
fuente
0

Los operadores por sí mismos no necesariamente devuelven nada. Las llamadas a funciones devuelven valores. Los operadores pueden generar valores. En ocasiones, los operadores pueden invocar funciones. Ejemplos incluyen:

• El operador de llamada de función.

• Un operador sobrecargado que se transforma en una llamada de función.

• operador nuevo, que se invoca como parte de una nueva expresión , es una llamada a función.

Mi único propósito al mencionar las llamadas a funciones es aclarar el resultado frente a la devolución. Según las 126 instancias de "retorno" y las palabras derivadas de él en [expr] , la sección parece usar cuidadosamente la palabra retorno para referirse a:

• el resultado de una llamada de función

• aspectos del flujo de control relacionados con las corrutinas

De acuerdo, eso es suficiente pedantería en el resultado frente a la devolución.

Saddam Kamal
fuente
0

Los operadores de C ++ devuelven algo o no, depende de cómo los use. Los operadores de C ++ incorporados devuelven algún valor hasta que, a menos que se apliquen, devuelvan vacío.


fuente