La expresión new int;como en int * x = new int;es una nueva expresión . El término "nuevo operador" parece usarse indistintamente con "nueva expresión", por ejemplo en esta pregunta: ¿ Diferencia entre 'nuevo operador' y 'operador nuevo'?
¿Es correcto decir que la palabra clave newtal como se usa en una nueva expresión es un operador? ¿Por qué o por qué no?
Si no es así, ¿existe otra justificación para llamar a una nueva expresión "nuevo operador"?
Tengo problemas para encontrar una definición autorizada de lo que constituye un operador.
Ya entiendo la distinción entre el operador nuevo que asigna memoria para un objeto y "nueva expresión" que eventualmente puede llamar a un operator new.
c++
language-lawyer
François Andrieux
fuente
fuente

newes comosizeofaquí. Y creo que la mayoría de la comunidad de C ++ piensasizeofen un operador. El stansard incluso se refiere al "sizeofoperador" cuando describe sus efectos.sizeof, yo diría que sería el operador de una expresiónsizeof(<type>). Y+es un operador para una expresión unaria<type> <op> <type>. Esa es mi conclusión / interpretación al menos, siéntete libre de corregirme.newes un operador o no, hay una diferencia entre una expresión y un operador. Por ejemplo,new intes una expresión que se evalúa como algo. Sinewse considera un operador, entonces sólo la parte "nueva" denew intes el operador (es decir, es su propia cosa separada). Conceptualmente, un operador es algo que actúa sobre otra cosa.Respuestas:
newinnew intno se considera un operador. Tampoco se considera que no sea un operador.El estándar C ++ es realmente vago, e incluso inconsistente, sobre lo que constituye un 'operador'. Cuando se enumeran los operadores (como se define durante el lexing y el preprocesamiento), los enumera junto con los "puntuadores" (cosas como
(), pero nunca da realmente ninguna regla para los puntuadores en general. Se enumeranewcomo palabra clave y como operador. Se enumerasizeofen el conjunto de palabras clave pero NO en el conjunto de operadores, pero luego se refiere a él como un operador.La conclusión aquí es que el comité de estándares de C ++ no está demasiado preocupado por separar el mundo léxico en "operadores" y "no operadores". Esto se debe a que realmente no es necesario. No hay reglas gramaticales que se apliquen a todos los operadores o no a todos los operadores. Los conjuntos importantes, como el conjunto de operadores sobrecargables , se proporcionan por separado; Las reglas gramaticales para cosas como expresiones aritméticas binarias se dan una a la vez.
Básicamente, "operador" no es una categoría que sea formalmente significativa para el lenguaje C ++, por lo que cualquier respuesta categórica se basará en cómo se "siente". Puede llamarlo operador si lo desea, pero también puede llamarlo una palabra clave (¡o un puntuador!) Y el estándar de idioma no estará en desacuerdo con usted.
fuente
operatory me imagino que, cuando alguien pide una delimitación exacta, es justo usar la palabra en inglés "operador" para las cosas que funcionan con esa palabra clave. En ese sentido,new,new[],delete,delete[],co_await, algunos typecasts, y conversiones de literales definidos por el usuario a los objetos serían operadores.operatorpalabra clave e incluyen cosas como.que no se pueden usar con laoperatorpalabra clave. Si me vieran forzado a punta de pistola a dar una definición de "operador", mi mente no iría a "operador sobrecargable".operatorpalabra clave, sí. Si me viera obligado a encontrar una delimitación absolutamente precisa de lo que es o no un operador, optaría por lo único que está definido con precisión en la gramática. En la comunicación diaria, no necesitaría tanta precisión todo el tiempo.No. En
newuna nueva-expresión es una palabra clave que identifica una nueva-expresión .Una nueva expresión llama una
operator newooperator new[]para obtener almacenamiento. También inicializa ese almacenamiento y lo desasigna (conoperator deleteooperator delete[]) si la inicialización arroja.Hay una clara distinción, ya que
operator newsolo se la conoce como una función reemplazable por el usuariosobrecargable, y una nueva expresión hace más que simplemente llamar a esta función.Referencia: 7.6.2.8/10
[expr.new]Considere, a modo de contraejemplo, que definimos tanto
T operator+(T, T); void* T::operator new(std::size_t);para algún tipo T, luego suma en cualquiera de las formas:
T a, b; T c = a + b; T d = T::operator +(a, b);es idéntico. La notación infija es simplemente azúcar sintáctica para la llamada del operador.
Sin embargo, la asignación se comporta de manera muy diferente:
T *p = new T; // does much more than void *v = T::operator new(sizeof(T));por lo que no es razonable llamar al azúcar sintáctico de nueva expresión para llamar a
operator new. Por lo tanto, lanewpalabra clave no es simplemente seleccionar la función a llamar. No puede ser, o tendría que mencionar laoperator deletefunción que también se podría llamar.fuente
operator newEs un operador sobrecargable", ¿verdad? Yo no lo creo:operator +no es un operador sobrecargable -+es, y que defino sobrecargas por medio de una función de llamadaoperator +.newpalabra clave tal como aparece en una nueva expresión.newesté sujeto a la sobrecarga del operador sugiere que la respuesta debería ser sí ,new(en sí mismo) es un operador.Solo lo llamaría nueva expresión para evitar confusiones con lo
void* operator new ( std::size_t count )que solo asigna memoria como parte del proceso que factura la nueva expresión (memoria de asignación, vida útil inicial, constructor de llamada).El problema con
newes que hace más que simplemente llamar aloperator new. Lo cual es un poco confuso porque es parax + ylas+únicas llamadasoperator +.fuente
Esto se rige por [expr.new] , que diferencia claramente entre una nueva expresión y cómo una nueva expresión puede obtener almacenamiento mediante la llamada a una función de asignación , que se nombra
operator new. En particular, de [expr.new] / 8 [ énfasis mío]:En particular, el ejemplo, aunque no normativo, de [expr.new] / 4 describe esta función como una función de operador; "[...] el
newoperador" :fuente
No.
Bueno, algo sí, en el sentido de que existen personas que se consideran
newennew intser un operador. Sin embargo, esta opinión está (en su mayoría) en desacuerdo con el estándar.En primer lugar,
[lex.operators/1]enumera los operadores en el idioma. No se deje engañar pensando que estos son simplemente "operadores de preprocesamiento"; no existe tal distinción en el sentido de operadores léxicos . Tampoco tendría sentido, ya que no puede (por ejemplo)++una macro.newes, de hecho, una palabra clave (por[lex.key/1]).A continuación, veamos la nueva expresión en sí. Aquí es donde las cosas se ponen un poco más confusas. Hay, por ejemplo, la siguiente redacción en
[expr.new/4]:Considero que esto es un error editorial, ya que está en desacuerdo con las definiciones proporcionadas anteriormente y no ocurre en ningún otro lugar de esa sección.
Luego llegamos a la sobrecarga del operador . En su producción gramatical para una declaración de operador, el terminal que enumera cosas (incluido
new) se denomina operador ([over.oper.general/1]). No creo que debamos preocuparnos por esto. Los nombres de terminales en la gramática nunca han tenido la intención de introducir definiciones de términos. Después de todo, tiene una expresión and que _no necesita ser una operación AND bit a bit; puede ser simplemente una expresión de igualdad :Es común definir gramáticas como esta, y ciertamente no significa que cada expresión de igualdad deba considerarse de alguna manera una invocación del operador AND bit a bit.
Finalmente, algunos han afirmado que la siguiente redacción (también en la sección de sobrecarga del operador) es una prueba de que de
newalguna manera ahora, de forma aislada, mágicamente es un operador:A ellos les digo, no sólo no está
newni siquiera en la lista, sino que está claramente usando el término "operador" en el sentido más amplio de "cosas que se pueden sobrecargar", aunquenewen sí mismo todavía no es un operador . También está en una nota no normativa, que debería decirle todo lo que necesita saber.Y, como usted mismo señala, ya lo consideramos
operator newotra cosa.fuente
sizeofes un operador. [expr.throw] es menos explícito con respecto a,throwpero todavía habla de un "operando"throw, lo que implica quethrowes un operador.Si bien sé que está buscando una respuesta semántica, en lo que a opinión respecta, diría que es una "palabra clave" (ya que está claramente reservada), y supongo que ambos sabemos que es simplemente la construcción de C ++ para la asignación de memoria. Dicho esto, cuando pienso en los "operadores" de C ++, tiendo a pensar en funciones con una entrada / salida establecida que se puede anular para tipos específicos. new es el mismo para todos los tipos (y, lo que es más confuso, puede anularse).
No estoy seguro de cuán oficial es cppreference, pero:
https://en.cppreference.com/w/cpp/language/new
Parece seguirse entonces que
new <type>es una expresión para asignar memoria, mientras quenewes el operador para esa expresión.Usando esa misma lógica:
sizeofes un "operador" para la expresiónsizeof(<type>)(aunquesizeofes un operador de "tiempo de compilación", un poco diferente de lo que estamos acostumbrados)+es un operador para una expresión<type> <operator> <type>throwes un operador para la expresiónthrow <throwaable>fuente
[]()también es un operador? Esfor? Esthrow?[]y()constituiría operadores separados. Nuevamente,fores absolutamente una palabra clave, pero donde delimitaría ser un operador fue la primera parte de poder ser anulado. Técnicamente, por eso,sizeofno es un operador, lo cual es cierto en C ++ en el sentido de que es más una expresión de preprocesamiento. Ythrowes un operador de una expresiónthrow <throwable>[]()a la combinación al definir una lambda. Pero su respuesta también es interesante porque (en C ++) la respuesta depende del contexto: infoo(),()es un operador (¡sobrecarga!); en(1 + 2)él no es un operador en absoluto (en algunos otros lenguajes, notablemente R, esto es diferente). De todos modos, el criterio anulable no es suficiente. Hay un montón de cosas en C ++ que son los operadores sin ambigüedades pesar de no ser sobrecargable (.,::,:?, ambossizeofs, etc).[]()como una lambda es una bestia difícil de definir (específicamente porque no estoy tan al día con mi C ++). Así que aquí todavía diría que[]()constituyen operadores diferentes de una expresión lambda , pero no estoy seguro de si argumentaría que no se pueden anular, o si el mismo acto de implementar / declarar una lambda constituye anular la lambda básica (como en Java). El diseño del lenguaje comienza a convertirse en un arte sobre la ciencia allí. En cuanto a( ... ), es un separador en la mayoría de los idiomas que he usado, pero echaré un vistazo a R muy rápido(a + b)es semánticamente idéntica a la llamada de función `(` (a + b), o, de hecho, `(` (`+` (a, b)), donde `x` puede usarse para hacer un nombrexse ajusta sintácticamente a una llamada de función en lugar de especial (como un operador infijo).